[英]Wait till first method is executed in all threads till execute second
我有一個小的演示代碼,其中有一個 Bean 類和 BeanRegister 類。 Bean 類有兩個方法preInit()
和postInit()
。 而 BeanRegister 是一個以 Bean 類為字段的線程類。 這是我的代碼:
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());
}
}
我面臨的問題是鎖定。 我想在所有線程中鎖定postInit()
,然后在這些線程中執行preInit()
方法沒有完成。 因此,當所有線程完成preInit()
的執行時,我想允許線程執行postInit()
。 任何想法如何以正確的方式做到這一點?
您可以使用跨所有線程共享的CountDownLatch
。
首先是一些理論:什么是CountDownLatch ?
這是一個非常簡單的並發實用程序,您可以使用某個整數(假設為 N)進行初始化。然后它為您提供了兩種方法:
countdown()
=> 每次調用它都會減少到N-1
await()
=> 它將停止當前線程,直到倒計時計數為零(如果需要,您可以指定超時)。 當然,這個類的最大優點是可以為您處理競爭條件(當您從某個線程調用countdown()
或await()
時,可以保證其他線程將看到正在發生的事情,而無需您處理任何內存屏障) .
所以現在,根據您的代碼,您首先讓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());
}
}
具體來說, preInit
會倒計時,而postInit
會在實際開始之前await
它為零。
然后,在您的調用函數中,您創建一個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();
}
}
}
樣本輸出:
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.