HOWTO · Java
Criar uma Lista Concorrente em Java
Este artigo apresenta como fazer uma lista concorrente em Java.
Nesta página
Simultaneidade é o processo de execução de programas ou funções paralelamente. Quando vários threads trabalham no mesmo método, isso permite uma redução do tempo e um aumento da taxa de transferência.
Java fornece a classe CopyOnWriteArrayList que permite uma maneira eficiente de operações List, e as funções funcionam de maneira thread-safe. Isso significa que quando duas ou mais threads tentam manipular a lista, a classe dada permite operações leitura-gravação de uma maneira segura para threads. Internamente, ao modificar métodos da interface de lista, como as funções adicionar ou remove, o conteúdo de CopyOnWriteArrayList é copiado para a nova cópia interna. Este recurso permite que ele seja seguro para thread e permite o processamento paralelo.
A classe CopyOnWriteArrayList está presente no pacote java.util.concurrent. Abaixo está um exemplo de bloco de código que demonstra as operações na classe fornecida.
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
public class ConcurrentListOperations {
public static void main(String[] args) {
List<Integer> temp_list = Arrays.asList(1, 2, 3);
List<Integer> list = new CopyOnWriteArrayList<>(temp_list);
new WriteThread("Writer", list).start();
new ReadThread("Reader", list).start();
}
}
class WriteThread extends Thread {
private final List<Integer> list;
public WriteThread(String name, List<Integer> list) {
this.list = list;
super.setName(name);
}
public void run() {
int count = 4;
int counter = 0;
do {
try {
Thread.sleep(5000);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
list.add(count++);
System.out.println(super.getName() + " done");
counter++;
} while (counter != 5);
}
}
class ReadThread extends Thread {
private final List<Integer> list;
public ReadThread(String name, List<Integer> list) {
this.list = list;
super.setName(name);
}
public void run() {
while (true) {
StringBuilder output = new StringBuilder("\n" + super.getName() + ":");
for (Integer nextVal : list) {
output.append(" ").append(nextVal);
}
System.out.println(output);
}
}
}
Classe de driver em Java
No programa acima, três classes são definidas. A primeira com o método main é a classe do driver, e outras estão lá para funcionar. Na classe ConcurrentListOperations, a lista temporária é inicializada com três inteiros inicialmente. A temp_list formada é passada para o construtor CopyOnWriteArrayList, que é outro tipo de classe ArrayList.
A classe inicializa a matriz com os valores definidos acima. Agora, a instância de copyOnWriteArrayList é passada para as classes de thread criadas anteriormente. Esta classe só tornará a lista thread-safe; portanto, permitindo operações paralelas na instância da lista.
Classe Thread em Java
As duas classes de thread são ReadThread e WriteThread. O trabalho real da classe é ler e escrever a mesma lista simultaneamente. A classe WriteThread estende a classe Thread, que é uma forma de declarar os threads. Ele tem um construtor público que atribui a instância da lista recebida à variável local e inicializa o nome do thread.
A lógica de negócios real para threads está presente em seu método run. Para iniciar um encadeamento, o método start é chamado sobre a instância da classe de encadeamento recém-criada.
Use o método run em Java
No método run da classe WriteThread, um contador é inicializado na condição de loop para rastrear as iterações da classe write no método run. O loop do-while é usado para controlar a contagem das execuções de iteração.
Dentro do bloco condicional, o método sleep da classe Thread é chamado para fazer o thread dormir pelo tempo definido. A função faz com que o paralelo, executando o segmento para dormir por uma quantidade definida de milissegundos. Ele lança IllegalArgumentException se os milissegundos passados forem negativos e InterruptedException se algum encadeamento for interrompido.
O método add é usado para adicionar elementos na lista por threads simultâneos. Ele lança UnsupportedOperationException se a operação não for permitida pela instância da lista. Por outro lado, lança ClassCastException se a classe do elemento especificado não for do mesmo tipo da lista. Ele lança NullPointerException se o valor especificado for nulo e IllegalArgumentException se alguma propriedade desse elemento impedir a adição do elemento.
Da mesma forma, no método run da classe ReadThread, um construtor é definido; ele inicializa o nome e a lista. O método run tem a lógica real read. A classe StringBuilder é usada para fazer manipulações na saída. O método append acrescenta a saída encontrada na classe de thread de gravação com a existente.
Conseqüentemente, as operações ler e escrever acontecem simultaneamente e são impressas no console no formato acima. O encadeamento de gravação dorme por cerca de 5.000 milissegundos e a saída do gravador será exibida menos vezes em comparação com o encadeamento lido. O ... significa que os encadeamentos estão em execução infinita e imprimindo a mesma saída porque nenhuma operação de gravação foi feita. Assim que o processo escrever for um sucesso, o encadeamento ler agora imprime o valor adicionado recentemente.
Produção:
Reader: 1 2 3
..
Writer done
Reader: 1 2 3 4
...
Writer done
Reader: 1 2 3 4 5