Java主线程发送信号然后等待其他非同步线程

时间:2018-06-02 17:24:07

标签: java multithreading java-threads

我正在学习Java中的线程,我试图做这样的事情:
我有一个带有值的矩阵,对于矩阵中的每个单元格,都有一个分配给它的线程,它会更新值(根据conway's game of life来确定)。线程应该一次更新矩阵的值,然后当它们全部完成时,主线程将显示更新的矩阵,然后询问用户是否应该计算下一步,这意味着开始再次进行相同的计算。
现在,我已经编写了几乎所有基本代码,包括线程以及它们如何更新他们负责的单元格,但我找不到主线程通知所有其他方法的方法线程醒来,完成工作,然后回去睡觉,并在他们现在完成工作后收到他们的通知。我尝试过使用wait()和notify()/ notifyAll()方法,但它们只适用于同步方法,我不需要在代码中实现这些方法(因为我&#39) ; m使用两个矩阵来确保首先所有线程都更新它们各自的单元格,然后只有当前矩阵才会成为下一代矩阵。
这是线程的run()方法:

public void run(boolean[][] currentGenMatrix) {
    updateLifeMatrix(currentGenMatrix);
    while(true) {
        try {
            wait();    // Wait for the next step before starting
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        updateLifeMatrix(m_nextGenMatrix);    // Update the current matrix to be the "next generation matrix" from the previous generation
        int neighbours = checkNeighbours(currentGenMatrix);
        m_nextGenMatrix[this.m_heightIndex][this.m_widthIndex] = setNewLifeOrDeath(neighbours, getCurrentLifeOrDeath(currentGenMatrix));    // Update the "next generation matrix" cell assigned to this thread
    }
}

在矩阵初始化期间,我在创建它们之后开始关闭所有线程,然后在进行第一步之前先等待通知。 我还阅读了有关显示器的信息,看看这是否符合我的要求,但我在网上看到的例子并不适合我的代码。

1 个答案:

答案 0 :(得分:0)

这是一个使用AcyclicBarrier的简单示例,其中两个工作线程由协调器线程(执行main方法的线程)控制。使用了两个障碍;所有工作线程都在等待启动障碍。当协调员等待该障碍时,障碍被打破,工人开始。为协调工作完成,所有N名工作人员以及协调员必须到达最后的障碍并打破它(等待它)。

package stackOv;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;

public class UseBarrier {

  public static void main(String[] args) throws Exception {
    int numThreads = 2 ;
    // one slot for the coordinator
    CyclicBarrier barrierStart = new CyclicBarrier(numThreads+1);
    CyclicBarrier barrierEnd = new CyclicBarrier(numThreads+1);

    Runnable work1 = new WorkerThread(barrierStart, barrierEnd, "work-0");
    Runnable work2 = new WorkerThread(barrierStart, barrierEnd, "work-1");
    new Thread(work1).start();
    new Thread(work2).start();

    while (true) {
      System.out.println("main: start");
      Thread.sleep(1000);
      barrierStart.await();
      System.out.println("waiting for workers..");
      barrierEnd.await();
      System.out.println("work finished, continue");
      Thread.sleep(1000);
    }
  }
}

class WorkerThread implements Runnable {
  private CyclicBarrier startWork;
  private CyclicBarrier endWork;
  private String name;
  public WorkerThread(CyclicBarrier startWork, CyclicBarrier barrier, String name) {
    this.startWork = startWork;
    this.endWork = barrier;
    this.name = name;
  }

  @Override
  public void run() {
    while (true) {
      try {
        System.out.println("worker "+name+": waiting");
        startWork.await();
        System.out.println("working.. "+name);
        Thread.sleep(1000);
        System.out.println("worker "+name+": done");
        endWork.await();
      } catch (BrokenBarrierException | InterruptedException e) {
        // depending on your application, you can either manage the
        // brokenBarrier exception, close your program (or ignore it)
      }
    }
  }
}