Pergunta

Estou escrevendo código que gerará dois threads e, em seguida, esperará que eles sincronizem usando a classe CyclicBarrier. O problema é que a barreira cíclica não está funcionando como o esperado e o encadeamento principal não espera que os threads individuais terminem. Veja como meu código parece:

 class mythread extends Thread{
   CyclicBarrier barrier;
   public mythread(CyclicBarrier barrier) { 
       this.barrier = barrier;
      }

   public void run(){
            barrier.await();
       } 
 }



class MainClass{
 public void spawnAndWait(){
    CyclicBarrier barrier = new CyclicBarrier(2);
    mythread thread1 = new mythread(barrier).start();
    mythread thread2 = new mythread(barrier).start();
    System.out.println("Should wait till both threads finish executing before printing this");
  }
}

Alguma ideia do que estou fazendo de errado? Ou existe uma maneira melhor de escrever esses métodos de sincronização de barreira? Por favor ajude.

Foi útil?

Solução

Durante a execução do seu tópico principal, você cria outros dois threads e diz para eles esperarem um pelo outro. Mas você não escreveu nada para fazer seu tópico principal para esperar por eles e reclamar que não espera. Tentar

CyclicBarrier barrier = new CyclicBarrier(3);
mythread thread1 = new mythread(barrier).start();
mythread thread2 = new mythread(barrier).start();
barrier.await(); // now you wait for two new threads to reach the barrier.
System.out.println("Should wait till both threads finish executing before printing this");

POR FALAR NISSO. Não estenda a classe de threads, a menos que você precise. Implemente o Runnable e passe implementações para os objetos Thread. Assim:

class MyRunnable implements Runnable {
    public void run(){
        // code to be done in thread
    }
}

Thread thread1 = new Thread(MyRunnable);
thread1.start();

EDITAR
Justificativa para evitar a extensão do encadeamento.
A regra geral é o mínimo possível de acoplamento. A herança é uma conexão muito forte entre as classes. Você precisa herdar do thread se deseja alterar parte de seu comportamento padrão (ou seja, substituir alguns métodos) ou querer acessar alguns campos protegidos do thread de classe. Se você não quiser, escolhe o acoplamento mais frouxo - implementando o Runnable e passando -o como um parâmetro construtor para a instância do encadeamento.

Outras dicas

Passe a Runnable instância para o construtor do seu CyclicBarrier assim.

CyclicBarrier barrier = new CyclicBarrier(2, new Runnable() {

    @Override
    public void run() {
        System.out.println("Should wait till both threads finish executing before printing this");
    }
});

new mythread(barrier).start();
new mythread(barrier).start();

Você está procurando Thread.Join () método...

thread1.join();
thread2.join();
System.out.println("Finished");

EDITAR: por causa dos comentários ...

E se você não quiser esperar para sempre, também pode especificar o número máximo de milissegundos mais nanossegundos para esperar que o tópico morra

A barreira cíclica não é a escolha correta neste caso. Você deve usar CountDownLatch aqui.

Eu suponho que você tem está invocando spawnAndWait Método do método principal.

A razão pela qual isso não funciona é que o CyclicBarrier tem 2 construtores. Para executar pós-operações, você deve usar um construtor de 2 parâmetros. A coisa mais importante a lembrar é que o tópico principal não vai esperar pelo await método; mas continuará a executar. No entanto, o tópico especificado no CyclicBarrier o construtor só funcionará quando todos os fios gerados pararem na barreira (pelo await método)

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top