Solucionado (ver solução)
Solucionado
(ver solução)
2
respostas

Thread Synchronized

Por quê nessa caso eu uso apenas o synchronized em bloco e não no método todo?

public class ProduzMensagens implements Runnable{
    private int comeco;
    private int fim;
    private Collection<String> mensagens;

    public ProduzMensagens(int comeco, int fim, Collection<String> mensagens) {
        this.comeco = comeco;
        this.fim = fim;
        this.mensagens = mensagens;
    }

    public void run() {
        for (int i = comeco; i < fim; i++) {
            synchronized(mensagens){
                mensagens.add("Mensagem " + i);
            }
        }
    }
}

Classe que utiliza:

import java.util.ArrayList;
import java.util.Collection;


/*******************************************************
 * Projeto: ThreadAlura
 * @author uz55541
 * Criada em 13/06/2014
 * $Date$
 * $Id$ 
 * Descrição: // TODO Descreva o objetivo desta classe aqui.
 *******************************************************/
public class RegistroDeMensagens {
    public static void main(String[] args) throws InterruptedException {
        Collection<String> mensagens = new ArrayList<String>();

        Thread t1 = new Thread(new ProduzMensagens(0, 10000, mensagens));
        Thread t2 = new Thread(new ProduzMensagens(10000, 20000, mensagens));
        Thread t3 = new Thread(new ProduzMensagens(20000, 30000, mensagens));

        t1.start();
        t2.start();
        t3.start();

        // faz com que a thread que roda o main aguarde o fim dessas
        t1.join();
        t2.join();
        t3.join();

        System.out.println("Threads produtoras de mensagens finalizadas!");

        // verifica se todas as mensagens foram guardadas
        for (int i = 0; i < 15000; i++) {
            if (!mensagens.contains("Mensagem " + i)) {
                throw new IllegalStateException("não encontrei a mensagem: " + i);
            }
        }

        // verifica se alguma mensagem ficou nula
        if (mensagens.contains(null)) {
            throw new IllegalStateException("não devia ter null aqui dentro!");
        }

        System.out.println("Fim da execucao com sucesso");
    }
}
2 respostas
solução!

Oi Adler,

a questão aqui é que teremos 3 threads rodando um for de 10000 adições de mensagens em uma mesma lista. Se colocarmos o synchronized no método inteiro, ele colocará todas as mensagens de uma thread, depois todas as de outra thread e finalmente todas da 3a.

Por exemplo, se a JVM escolhesse rodar t1 primeiro, as outras threads ficariam esperando até os 10000 números da t1 fossem adicionados. Fica quase que sequêncial.

Colocando o synchronized apenas dentro do for, a cada adição nas mensagens, o escalonador da JVM tem a escolha de alternar as threads.

Aí sim, é que haverá concorrência e valerá mais a pena usar as threads.

Muito obrigado Cecilia.