Java 主线程发送信号然后等待其他非同步线程
Java main thread sending signal and then waiting for other non-synchronized threads
我正在学习 Java 中的线程,我正在尝试做这样的事情:
我有一个包含值的矩阵,对于矩阵中的每个单元格,都有一个线程分配给它,它更新值(根据 conway's game of life)。线程应该全部更新一次矩阵的值,然后当它们全部完成时,主线程将显示更新后的矩阵,然后询问用户是否也应该计算下一步,这意味着重新开始相同的计算.
现在,我已经编写了几乎所有的基本代码,包括线程以及它们如何更新它们所负责的单元格,但是我找不到主线程通知所有其他线程唤醒的方法,做他们的工作,然后回去睡觉,并在他们暂时完成工作后收到他们的通知。我试过使用 wait() 和 notify()/notifyAll() 方法,但它们仅适用于同步方法,我不需要在代码中实现(因为我使用两个矩阵来确保首先所有线程更新它们各自的单元格,然后当前矩阵才会成为下一代矩阵)。
这是线程的 运行() 方法:
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
}
}
在矩阵初始化的时候,我把所有的线程都创建好之后就启动了,然后它们先等待通知,然后才开始执行第一步。
我还阅读了有关监视器的内容,看看它是否是我需要的,但是我在网上看到的示例不适合我的代码。
这是一个使用 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)
}
}
}
}
我正在学习 Java 中的线程,我正在尝试做这样的事情:
我有一个包含值的矩阵,对于矩阵中的每个单元格,都有一个线程分配给它,它更新值(根据 conway's game of life)。线程应该全部更新一次矩阵的值,然后当它们全部完成时,主线程将显示更新后的矩阵,然后询问用户是否也应该计算下一步,这意味着重新开始相同的计算.
现在,我已经编写了几乎所有的基本代码,包括线程以及它们如何更新它们所负责的单元格,但是我找不到主线程通知所有其他线程唤醒的方法,做他们的工作,然后回去睡觉,并在他们暂时完成工作后收到他们的通知。我试过使用 wait() 和 notify()/notifyAll() 方法,但它们仅适用于同步方法,我不需要在代码中实现(因为我使用两个矩阵来确保首先所有线程更新它们各自的单元格,然后当前矩阵才会成为下一代矩阵)。
这是线程的 运行() 方法:
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
}
}
在矩阵初始化的时候,我把所有的线程都创建好之后就启动了,然后它们先等待通知,然后才开始执行第一步。 我还阅读了有关监视器的内容,看看它是否是我需要的,但是我在网上看到的示例不适合我的代码。
这是一个使用 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)
}
}
}
}