简体   繁体   English

等到第一个方法在所有线程中执行,直到执行第二个

[英]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:所以现在,根据您的代码,您首先让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());
    }
}

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM