簡體   English   中英

等到第一個方法在所有線程中執行,直到執行第二個

[英]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()時,可以保證其他線程將看到正在發生的事情,而無需您處理任何內存屏障) .

所以現在,根據您的代碼,您首先讓BeanpreInitpostInit方法采用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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM