java - 加入两个不同的 ExecutorService
问题描述
我想加入两个在 ExecutorService 中执行的线程。
public class CURD {
public static ExecutorService executorService = Executors.newCachedThreadPool();
@Autowired
Logging logging;
public void Update(List<? extends HBase> save, List<? extends HBase> delete) {
Thread t = new Thread(() -> {
System.out.println("Started Main Thread...");
try {
Thread.sleep(1500);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("End Main Thread...");
},"Thread-1");
logging.setPredecessor(t);
executorService.submit(t);
}
}
第二类:这个类线程应该等待第一个线程完成。但它不会等待第一个线程完成。我不确定这是否是正确的方法。
请问有人可以让我知道如何加入在 ExecutorService 中执行的两个线程吗?
import static com.demo.executorService;
public class Logging {
private Thread predecessor;
public void setPredecessor(Thread t) {
this.predecessor = t;
}
private void loggingInfo() {
Thread run = new Thread( () ->{
try {
if (predecessor != null) {
System.out.println(Thread.currentThread().getName() + " Started");
predecessor.join();
System.out.println(Thread.currentThread().getName() + " Finished");
}
} catch (InterruptedException e) {
e.printStackTrace();
}
});
addTask(run);
}
public void addTask(Runnable run) {
System.out.println("Runnable Thread logAround.....");
CompletableFuture.runAsync((run), executorService).exceptionally(ex -> {
System.out.println("exception occurred " + ex);
return null;
});
}
}
解决方案
如果想在一组线程之间进行同步,可以使用 Java CyclicBarrier类:
一种同步辅助工具,它允许一组线程相互等待以达到共同的障碍点。CyclicBarriers 在涉及固定大小的线程组的程序中很有用,这些线程组必须偶尔相互等待。屏障被称为循环的,因为它可以在等待线程被释放后重新使用。
为此,首先创建CyclicBarrier
具有相应数量的对象,即:
private final CyclicBarrier barrier = new CyclicBarrier(NUMBER_OF_PARIES);
正式地从 Java 文档中可以读到各方是:
在触发屏障之前必须调用 {@link #await} 的线程数
非正式地,各方是必须调用循环屏障并等待的线程数,然后它们才能继续前进。
之后,您需要将屏障实例对象引用传递给应该等待的每个线程,并相应地调用wait
(即 barrier.await()
)。如下所示:
public void Update(..., CyclicBarrier barrier) {
Thread t = new Thread(() -> {
System.out.println("Started Main Thread...");
try {
Thread.sleep(1500);
barrier.await(); // <--- wait on the barrier
} catch (InterruptedException | BrokenBarrierException e) {
e.printStackTrace();
}
System.out.println("End Main Thread...");
},"Thread-1");
...
}
对必须等待的其他线程重复此过程。确保参与方的数量(即 NUMBER_OF_PARIES
)与应在循环屏障上等待的线程数相匹配,否则会发生死锁。
现在您正在使用 ,cyclic barrier
您可以清理代码的某些部分,例如,您可以删除与类字段相关的所有predecessor
逻辑Logging
。
如果您只想Thread 2
等待Thread 1
,那么您可以使用CountDownLatch来代替。
一种同步辅助,允许一个或多个线程等待,直到在其他线程中执行的一组操作完成。CountDownLatch 使用给定的计数进行初始化。由于调用了 countDown() 方法,等待方法一直阻塞,直到当前计数达到零,之后所有等待的线程都被释放,任何后续的 await 调用立即返回。这是一次性现象——计数无法重置。如果您需要重置计数的版本,请考虑使用 CyclicBarrier。
首先创建CountDownLatch
只有1
计数的对象:
private final CountDownLatch block_thread2 = new CountDownLatch(1);
并将其传递给Thread 2
, 并且由于您希望该线程等待Thread 1
, 调用block_thread2.await();
Thread run = new Thread( () ->{
try {
....
block_thread2.await(); // wait for Thread 2
} catch (InterruptedException e) {
// deal with it
}
});
...
并Thread 1
添加 wait.countDown();
:
public void Update(...) {
Thread t = new Thread(() -> {
System.out.println("Started Main Thread...");
try {
Thread.sleep(1500);
wait.countDown();
} catch (InterruptedException e) {
// deal with it
}
System.out.println("End Main Thread...");
},"Thread-1");
...
}
所以,以这种方式,Thread 2
会等待Thread 1
,但Thread 1
永远不会等待Thread 2
。
推荐阅读
- java - 使用 JAMOD 读取正确的 Schneider Momentum PLC 寄存器或线圈地址
- python - 将输出标签值保存到 csv
- python - 在两个 RaspberryPi 之间使用 Python xmlrpc 会导致连接被拒绝错误
- javascript - HTML & CSS: 带有基于 Scroll 的覆盖导航栏的嵌入式视频
- angular - 从 Angular 到 Spring 的多部分发布请求
- python - Python Twisted/Reactor 无法将消息发送到服务器/客户端
- python - 如何计算熊猫系列中列表的元素
- django - Letsencrypt 登台和生产服务器上的 SSL 证书
- regex - 正则表达式禁止撇号和连字符之前或之后的任何空格
- homebrew - 当存在相同版本的两个副本时,我应该如何覆盖/替换 nmap?