Ola em meu sistema estou utlilizando em algumas situações LinkedList e LinkedHashMap. Minha dúvida é ambas possuem sincronização, pois tenho a seguinte situação:
public class A {
public A() {
sendList = new LinkedHashMap<String, Tarefa>();
this.start();
}
public void run() {
....
sendList.put("001",tarefa);
....
}
}
public class B {
public B(A a) {
this.a = a;
this.sendList = a.sendList;
this.start();
}
public void run() {
...
if (!sendList.isEmpty()) {
job = sendList.remove("001");
} else {
System.out.println("\t Lista de tarefas enviados vazia \n");
}
...
}
}
O que esta ocorrendo é que a mensagem de lista vazia esta sendo impressa. Não sei o que pode estar ocorrendo pois a class A é instânciada primeiro e somente depois a classe B. É necessário utilizar algum tipo de sincronização? Como posso fazer?? A mesma situação está ocorrendo com LinkedList
A sincronização ocorre dentro do método, mas não entre métodos:
Portanto, pode haver preempção entre esse teste, e a entrada do if:
if (!sendList.isEmpty()) {
job = sendList.remove("001");
Cuidado, não é porque sua estrutura é sincronizada, que os métodos que a utilizarão serão também.
Por isso, na maior parte das vezes, a sincronização das classes Vector e HashTable são inúteis: o que deve ser sincronizado é o método que as usam, não elas em si.
entendi mais ou menos :D, pra variar mais para menos. Neste caso por estar utilizando multithrad é necessario utilizar sincronização entre as threads? Se sim, como posso fazer? teria algum material em específico para ler?
É necessário sim. Como as duas threads compartilham memória (a lista), é necessário sincronização.
Quanto a leitura, na internet não sei de muitos lugares. Tem os artigos do Brian Goetz, mas são mais avançados.
Eu comprei foi um livro dele, chamado Java Concurrency In Practice. Muito bom.
Mas se eu utilizar:
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
solucionaria o meu problema? e ae eu etiver utilizando uma lista de mapas? seria ConcurrentHashMap?
A sincronização da lista garante apenas que no meio de um método da lista (ou da queue, ou do map), outro não vai ser chamado. Por exemplo, que no meio de uma operação de add, uma operação de remove não vai ser chamada.
Agora, ela não garante nada do que possa ocorrer entre duas operações. Por exemplo, o seu if. Ele primeiro testa isEmpty(), em seguida, tenta remover algo.
Pode ocorrer de uma thread testar isEmpty(), a preempção ocorrer, outra fazer um insert. E o put não ser executado.
Como eu falei, você precisa estudar um pouco como funciona a sincronização dos seus próprios métodos.
Ou alterar seu código para usar apenas 1 método da lista por vez. O LinkedBlockingQueue torna isso possível por ter métodos como put() e take(), que já faz a espera automaticamente se a lista está vazia ou cheia.