[英]Wait till first method is executed in all threads till execute second
I have a small demo code where I have a Bean class and BeanRegister class.我有一个小的演示代码,其中有一个 Bean 类和 BeanRegister 类。 Bean class has two methods which are
preInit()
and postInit()
. Bean 类有两个方法
preInit()
和postInit()
。 And BeanRegister is a thread class which has Bean class as a field.而 BeanRegister 是一个以 Bean 类为字段的线程类。 Here my code:
这是我的代码:
public static void main(String[] args) {
Bean beanA = new Bean();
BeanRegister beanRegister1 = new BeanRegister(beanA);
BeanRegister beanRegister2 = new BeanRegister(beanA);
beanRegister1.start();
beanRegister2.start();
}
private static class BeanRegister extends Thread {
private final Bean bean;
public BeanRegister(Bean bean) {
this.bean = bean;
}
@Override
public void run() {
try {
bean.preInit();
bean.postInit();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
private static class Bean {
public void preInit() throws InterruptedException {
Thread.sleep(new Random().nextInt(1000) * 5);
System.out.println("PreInit +" + Thread.currentThread().getName());
}
public void postInit() throws InterruptedException {
System.out.println("PostInit +" + Thread.currentThread().getName());
}
}
The problem I faced, is locking.我面临的问题是锁定。 I want to lock
postInit()
in all threads, before those execution of preInit()
method in those threads is not finished.我想在所有线程中锁定
postInit()
,然后在这些线程中执行preInit()
方法没有完成。 So, when all threads finished execution of preInit()
, then I want to allow threads to execute postInit()
.因此,当所有线程完成
preInit()
的执行时,我想允许线程执行postInit()
。 Any ideas how to do it in proper way?任何想法如何以正确的方式做到这一点?
You can use a CountDownLatch
which is shared across all threads.您可以使用跨所有线程共享的
CountDownLatch
。
Some theory first: what is a CountDownLatch ?首先是一些理论:什么是CountDownLatch ?
It's a very simple concurrent utility which you initialize with a certain integer, let's say N. It then offers you two methods:这是一个非常简单的并发实用程序,您可以使用某个整数(假设为 N)进行初始化。然后它为您提供了两种方法:
countdown()
=> it will decrease to N-1
each time that is called countdown()
=> 每次调用它都会减少到N-1
await()
=> it will stop the current thread until when the count of the countdown is zero (you can specify a timeout if wished). await()
=> 它将停止当前线程,直到倒计时计数为零(如果需要,您可以指定超时)。 Of course, the great advantage of this class is that race conditions are handled for you (when you call countdown()
or await()
from a certain thread, you are guaranteed that other threads will see what's happening without you handling any memory barrier).当然,这个类的最大优点是可以为您处理竞争条件(当您从某个线程调用
countdown()
或await()
时,可以保证其他线程将看到正在发生的事情,而无需您处理任何内存屏障) .
So now, based on your code, you start by making the preInit
and postInit
methods of Bean
taking a CountDownLatch
in parameter:所以现在,根据您的代码,您首先让
Bean
的preInit
和postInit
方法采用CountDownLatch
参数:
private static class Bean {
public void preInit(CountDownLatch latch) throws InterruptedException {
Thread.sleep(new Random().nextInt(1000) * 5);
System.out.println("PreInit +" + Thread.currentThread().getName());
latch.countDown(); //<-- each time one preInit ends, decrease the countdown by 1
}
public void postInit(CountDownLatch latch) throws InterruptedException {
latch.await(); //<-- even if you're called here, wait until when the countdown is at zero before starting execution
System.out.println("PostInit +" + Thread.currentThread().getName());
}
}
Specifically, the preInit
will count it down, while the postInit
will await
for it to be at zero before actually starting.具体来说,
preInit
会倒计时,而postInit
会在实际开始之前await
它为零。
Then, in your calling function you create a new CountDownLatch(2)
(where 2
is the number of independent threads) and you simply push it down in the call stack:然后,在您的调用函数中,您创建一个
new CountDownLatch(2)
(其中2
是独立线程的数量),您只需将其下推到调用堆栈中:
public static void main(String[] args) {
Bean beanA = new Bean();
CountDownLatch latch = new CountDownLatch(2);
BeanRegister beanRegister1 = new BeanRegister(beanA, latch);
BeanRegister beanRegister2 = new BeanRegister(beanA, latch);
beanRegister1.start();
beanRegister2.start();
}
private static class BeanRegister extends Thread {
private final Bean bean;
private final CountDownLatch latch;
public BeanRegister(Bean bean, CountDownLatch latch) {
this.bean = bean;
this.latch = latch;
}
@Override
public void run() {
try {
bean.preInit(latch);
bean.postInit(latch);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Sample output:样本输出:
PreInit +Thread-1
PreInit +Thread-0
PostInit +Thread-1
PostInit +Thread-0
Process finished with exit code 0
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.