java - 并行线程需要到达一个点,等待另一个线程,然后恢复 - 最好的方法?
问题描述
这是(简化的)场景:
- 我有线程 A、B、C 并行运行。
- 一旦所有 3 个线程都达到了执行的第 7 步,它们必须等待。(每个线程会在不同的时间到达Step 7,无法提前知道)。
- 然后线程 D 启动并运行到完成。
- 只有在 D 完成后,A、B 和 C 才能恢复并运行到完成。
什么是解决这个问题的好工具或设计?
到目前为止,我看到的并发和信号量示例似乎只处理 2 个线程,或者假设并行线程正在做类似的事情,但只是共享一个 var 或消息传递。我还没有找到任何适用于上述场景的东西。我正在继续研究它,并将更新任何发现。
如果不需要让其他线程退出,则 CountDownLatch 可能会起作用。或者如果它可以反向工作 - 让n
线程等到线程 D 退出。
我对并发相当陌生(大学课程不会在它需要的任何时间提供它),所以请耐心等待。如果有类似问题的人偶然发现此线程,请在此处删除此链接:HowToDoInJava - Concurrency
解决方案
我会使用移相器
import java.util.concurrent.Phaser;
class Scratch {
public static class ThreadABCWorker implements Runnable {
String threadName;
Phaser phaser;
public ThreadABCWorker(String threadName, Phaser phaser) {
this.threadName = threadName;
this.phaser = phaser;
}
@Override
public void run() {
System.out.println("Thread " + threadName + " has started");
// do steps 1-7 as part of phase 0
phaser.arriveAndAwaitAdvance();
// All the work for phase 1 is done in Thread D, so just arrive again and wait for D to do its thing
phaser.arriveAndAwaitAdvance();
System.out.println("Continue Thread" + threadName);
}
}
public static void main(String[] args) {
var phaser = new Phaser(4);
var threadA = new Thread(new ThreadABCWorker("A", phaser));
var threadB = new Thread(new ThreadABCWorker("B", phaser));
var threadC = new Thread(new ThreadABCWorker("C", phaser));
var threadD = new Thread(() -> {
phaser.arriveAndAwaitAdvance(); // D shouldn't start doing its thing until phase 1
System.out.println("Thread D has started");
try {
System.out.println("sleep 100");
Thread.sleep(100);
System.out.println("Thread D has finished");
phaser.arriveAndDeregister(); // All done, let ths other threads continue
} catch (InterruptedException e) {
e.printStackTrace();
}
});
threadA.start();
threadB.start();
threadC.start();
threadD.start();
}
}
示例输出:
Thread A has started
Thread C has started
Thread B has started
Thread D has started
sleep 100
Thread D has finished
Continue ThreadB
Continue ThreadA
Continue ThreadC
推荐阅读
- php - 如何在 Stripe Oauth 过程中恢复 php 会话
- mysql - 来自工会的玛丽亚更新 - 或建议
- c# - String.用逐字字符串替换
- python - 我如何编程这个骰子滚轮?
- postgresql - 使用 Data Studio 进行 Postgres 数据库身份验证时出错
- css - GtkScrolledWindow - 如何始终显示覆盖滚动条
- azure-service-fabric - 如何在 Linux 上的 Service Fabric 中查看死机或崩溃容器的日志?
- sql - 如何从减号查询中插入带有预选值的表?
- pytest - 如何从 tmpdir_factory 读取文件
- electron - 在不自动启动的情况下安装 Electron 应用程序