Eu tenho uma ArrayList que desejo usar para conter objetos RaceCar que estendem a classe Thread assim que sua execução for concluída. Uma classe, chamada Race, trata este ArrayList usando um método de retorno de chamada que o objeto RaceCar chama quando termina de ser executado. O método de retorno de chamada, addFinisher (RaceCar finisher), adiciona o objeto RaceCar ao ArrayList. Isso deve fornecer a ordem na qual os Threads terminam de ser executados.
Eu sei que ArrayList não está sincronizado e, portanto, não é seguro para thread. Tentei usar o método Collections.synchronizedCollection (c Collection) passando uma nova ArrayList e atribuindo a coleção retornada a uma ArrayList. No entanto, isso me dá um erro de compilador:
Race.java:41: incompatible types
found : java.util.Collection
required: java.util.ArrayList
finishingOrder = Collections.synchronizedCollection(new ArrayList(numberOfRaceCars));
Aqui está o código relevante:
public class Race implements RaceListener {
private Thread[] racers;
private ArrayList finishingOrder;
//Make an ArrayList to hold RaceCar objects to determine winners
finishingOrder = Collections.synchronizedCollection(new ArrayList(numberOfRaceCars));
//Fill array with RaceCar objects
for(int i=0; i<numberOfRaceCars; i++) {
racers[i] = new RaceCar(laps, inputs[i]);
//Add this as a RaceListener to each RaceCar
((RaceCar) racers[i]).addRaceListener(this);
}
//Implement the one method in the RaceListener interface
public void addFinisher(RaceCar finisher) {
finishingOrder.add(finisher);
}
O que preciso saber é se estou usando uma abordagem correta e, se não, o que devo usar para tornar meu código thread-safe? Obrigado pela ajuda!
List
interface não é realmente completa o suficiente para ser muito útil em multithreading.)Collections.synchronizedList()
, teríamos uma condição de corrida REAL aqui: PRespostas:
Use
Collections.synchronizedList()
.Ex:
fonte
mudança
para
List é um supertipo de ArrayList, então você precisa especificar isso.
Caso contrário, o que você está fazendo parece bom. Outra opção é que você pode usar o Vector, que é sincronizado, mas provavelmente é o que eu faria.
fonte
List
provavelmente seria mais útil. OuList<RaceCar>
.//Print out winner System.out.println("The Winner is " + ((RaceCar) finishingOrder.get(0)).toString() + "!");
ele está dizendo que o método get (0) não foi encontrado. Pensamentos?CopyOnWriteArrayList
Use a
CopyOnWriteArrayList
classe. Esta é a versão de thread seguraArrayList
.fonte
ConcurrentLinkedQueue
Você pode estar usando a abordagem errada. Só porque um thread que simula um carro termina antes de outro thread de simulação de carro, não significa que o primeiro thread deve vencer a corrida simulada.
Depende muito da sua aplicação, mas pode ser melhor ter um thread que calcule o estado de todos os carros em pequenos intervalos de tempo até que a corrida seja concluída. Ou, se preferir usar vários tópicos, você pode fazer com que cada carro registre o tempo "simulado" que levou para completar a corrida e escolher o vencedor como aquele com o menor tempo.
fonte
Você também pode usar uma
synchronized
palavra-chave para umaddFinisher
método como estePortanto, você pode usar o método ArrayList add thread-safe desta forma.
fonte
final Object
sempre que acessar deCollection
alguma forma.Sempre que você quiser usar a versão ant thread safe do objeto de coleção de formigas, peça ajuda do pacote java.util.concurrent. * . Ele tem quase todas as versões simultâneas de objetos de coleção não sincronizados. por exemplo: para ArrayList, você tem java.util.concurrent.CopyOnWriteArrayList
Você pode fazer Collections.synchronizedCollection (qualquer objeto de coleção), mas lembre-se deste synchr clássico. a técnica é cara e vem com sobrecarga de desempenho. pacote java.util.concurrent. * é menos caro e gerencia o desempenho de uma maneira melhor usando mecanismos como
Portanto, prefira algo do pacote java.util.concurrent. *
fonte
Você também pode usar como Vector em vez disso, já que os vetores são thread-safe e arraylist não. Embora os vetores sejam antigos, eles podem resolver seu propósito facilmente.
Mas você pode fazer seu Arraylist sincronizado como código, dado o seguinte:
fonte
Você pode mudar de ArrayList para o tipo Vector, em que todos os métodos são sincronizados.
fonte