3
respostas

Como os valores da variável da classe chamadora foi modificado sem ao menos o método da classe que foi chamada possuir método que retorna informações

Como a collection de strings chamada mensagens que no início estava vazia e foi passada para o construtor da classe ProduzMensagens contém as mensagens produzidas pelo código da classe ProduzMensagens ?

No meu entendimento somente a this.mensagens da classe ProduzMensagens deveria conter as mensagens criadas no código da classe ProduzMesangens.

Abaixo segue o código fonte:

Classe de teste que chama a classe ProduzMensagens:

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 deveria tere null aqui dentro!");
        }

        System.out.println(mensagens);

        System.out.println("Fim da execução com sucesso");


    }

}

Segue a classe que gera as mensagens:

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;
    }

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

    public Collection<String> getMensagens() {
        return mensagens;
    }

    public void setMensagens(Collection<String> mensagens) {
        this.mensagens = mensagens;
    }

}
3 respostas

Thiago, tudo bem ?

Como você gerou num escopo a referencia fica visível para todos. Tanto que você a repassa em todos os objetos que foram criados, então a referencia da sua coleção está disponível em ambas as threads, que podem a manipular tranquilamente.

Oi Matheus, boa tarde. Grato pelo retorno, mas ainda fiquei com dúvidas no que me disse. Segue: No programa: RegistroDeMensagens, criei a variável mensagens que é uma coleção, depois passei ela para a classe ProduzMensagens. Dentro da classe ProduzMensagens eu atribuo a coleção que criei na anterior na coleção de mesmo tipo da própria classe (this.mensagens = mensagens). Sendo assim, o this.mensagens é que recebe "Vazio" da coleção que criei na classe anterior, a mensagens. A partir daí na classe ProduzMensagens somente a this.mensagens é modificada pela classe... é essa minha dificuldade para entender o que houve "por baixo dos panos" que a collection mensagens da classe RegistroDeMensagens foi preenchido com as mensagens produzidas na classe ProduzMensagens.

Thiago, tudo bem ?

Você disse que na sua classe ProduzMensagens, que o atributo dela vai ter a referencia das mensagens que você está passando, por exemplo : 91u2jasnd@Collletions

E todas as suas instancias estão recebendo a mesma referencia de memoria : 91u2jasnd@Collletions, o que faz com que ao ler essa referencia tenham todas as mensagens.