当前位置:网站首页>How to cooperate among multiple threads

How to cooperate among multiple threads

2022-07-07 19:57:00 Ma Nong, little fat brother

1. CountDownLatch Counter

When multithreading cooperates to complete tasks , Sometimes you need to wait for other threads to complete the task , The main thread can continue to execute , We can use  Thread  Class  join()  Method , Let the main thread wait to be join After the thread of executes, the main thread executes . Of course, it can also be realized through the message communication of threads , But today we There is a tool in the contract , It is very convenient to complete this task .

Take a popular example , Two dogs lead soldiers to fight , altogether 6 A little soldier , There is no order from general ergouzi , Dare not attack rashly , The attack will become cannon fodder . So Er Gouzi gave an order , All the soldiers went crazy and shouted at the duck , Kill the enemy .

Little soldiers are like 6 Threads , Two dogs are like main threads , When a thread calls  CountDownLatch.countDown()  Method, the value of the counter -1, Until the value of the counter is 0 When , call await Method thread To carry on .

CountDownLatch  An important method of

public CountDownLatch(int count)

The constructor passes in a Plastic figure N, Then call  countDown()  The method will be right N reduce 1, until N = 0 , The current call  await  Method to continue execution , Otherwise, it will be blocked .

CountDownLatch There are not many ways , List them one by one :

  1. await() throws InterruptedException: The thread calling the method waits until the construction method passes in N Reduced to 0 When , To carry on ;

  2. await(long timeout, TimeUnit unit): With the above await Method function is consistent , It's just that there's a time limit , The thread that calls the method waits until the specified timeout After time , No matter N Is it reduced to 0, Will continue to carry out ;

  3. countDown(): send CountDownLatch Initial value N reduce 1;

  4. long getCount(): Get current CountDownLatch Maintenance value ;

1.1 Follow my orders to attack the city

General ergouzi led his troops to attack the city , Define our Little soldier

publicclass Soldier implements Runnable {

    privatefinal CountDownLatch doneSignal;

    public Soldier(CountDownLatch doneSignal) {
        this.doneSignal = doneSignal;
    }

    @Override
    public void run() {
        try {
            System.out.println("name = " + Thread.currentThread().getName() + " Go to battle to kill the enemy , Blunt duck ");
        } finally {
            //  Yes, the counter  - 1
            doneSignal.countDown();
        }
    }
}

Then simulate our two dogs to give orders

publicclass Commander {

    public static void main(String[] args) throws InterruptedException {

        int n = 6;
        //  The initialization counter is  6
        CountDownLatch doneSignal = new CountDownLatch(n);
        ExecutorService e = Executors.newFixedThreadPool(n);

        // simulation  6  Threads 
        for (int i = 0; i < n; ++i) {
            e.execute(new Soldier("doneSignal" + i, doneSignal));
        }
        System.out.println(" All soldiers in position , Follow my orders ");
        //  When  doneSignal  Every time you execute  countDown - 1  operation , Turned into  0  Then all threads wake up to execute 
        doneSignal.await();
        System.out.println(" Successful siege , Go back and ask for credit and reward. Eat sheep and scorpions to make up ");
        e.shutdown();
    }

}

1.2 Running races , Timing begins

When athletes run , Suppose there is 6 Athletes compete , The referee will be here at the finish line 6 The athletes timed separately , It is conceivable that when an athlete reaches the finish line , For the referee, there is one less timing task .

Until all the athletes have reached the finish line , The referee's task has just been completed . this 6 An athlete can be compared to 6 Threads , When a thread calls CountDownLatch.countDown Method will decrement the value of the counter by one , Until the value of the counter is 0 When , Referee ( call await Method thread ) To carry on .

publicclass Running {

    public static void main(String[] args) throws InterruptedException {
        //  Referee start signal 
        CountDownLatch startSignal = new CountDownLatch(1);

        int number = 4;
        //  Athlete running completion signal 
        CountDownLatch doneSignal = new CountDownLatch(number);

        ExecutorService executorService = Executors.newFixedThreadPool(number);
        for (int i = 0; i < number; i++) {
            finalint currnt = i;
            executorService.execute(() -> {
                try {
                    //  Let all the athletes wait and block here , Until the signal is sent 
                    startSignal.await();
                    System.out.println(Thread.currentThread().getName() + " Take a step and run hard ");
                    TimeUnit.SECONDS.sleep(currnt);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    //  After running 
                    doneSignal.countDown();
                    System.out.println(Thread.currentThread().getName() + " Reach the end point ");
                }
            });
        }
        System.out.println(" The referee gives orders !!!");
        startSignal.countDown();
        // Wait for all the athletes to finish 
        doneSignal.await();
        System.out.println(" All the athletes reached the finish line , The game is over !");

        executorService.shutdown();

    }
}

2. Recycling fence :CyclicBarrier

and  CountDownLatch  It also has the function of waiting for counting , But compared to  CountDownLatch  More powerful .

6eccd3c7cd3f593f75a759f2e7db9e26.png

It is also a popular example , Marathon , Many athletes , But the runway is limited, and only 6 Athletes start running , Every time I wait 6 Just run , Then the next team , Cycle all the time ....

At the beginning of the game , Need 6 All the athletes stood at the starting point at the beginning of the game , The referee whistled before he started running . The starting point of the runway is equivalent to “barrier”, It's the tipping point , And this 6 An athlete is analogous to a thread , This is the 6 Each thread must reach the specified point , It means a wave of , Then you can continue , Otherwise, each thread has to block and wait , Until you get together a wave .cyclic It means cycle , in other words CyclicBarrier When multiple threads gather together a wave , Still valid , Can continue to gather up the next wave .

// Wait until all threads reach the specified critical point 
await() throws InterruptedException, BrokenBarrierException

// With the above await The function of the method is basically the same , It's just that there's a timeout limit , Block waiting until the timeout is reached 
await(long timeout, TimeUnit unit) throws InterruptedException,
BrokenBarrierException, TimeoutException

// Gets how many threads are currently blocked waiting at the critical point 
int getNumberWaiting()

// Used to query whether the thread blocking waiting is interrupted 
boolean isBroken()


// Reset the barrier to its initial state . If a thread is currently waiting at the critical point , Will throw out BrokenBarrierException.
void reset()

Another thing to note ,CyclicBarrier Provides such a construction method :

public CyclicBarrier(int parties, Runnable barrierAction)

Can be used to , When the specified threads have reached the specified critical point , The next operation can be performed by barrierAction Just pass it in . A callback method .

Marathon code example

publicclass CyclicBarrierDemo {

    private CyclicBarrier cyclicBarrier;

    private ExecutorService executorService;

    public CyclicBarrierDemo(CyclicBarrier cyclicBarrier) {
        this.cyclicBarrier = cyclicBarrier;
        executorService = Executors.newFixedThreadPool(cyclicBarrier.getParties());
    }

    public void startRun() {

        for (int i = 0; i < cyclicBarrier.getParties() * 3; i++) {
            int current = i;
            executorService.execute(() -> {
                try {
                    System.out.println(Thread.currentThread().getName() + " Athletes , Be ready ");
                    //  Every athlete will   Yes  N - 1, Turn into  0  Then put a wave of threads to run , Then reset  N
                    cyclicBarrier.await();
                    System.out.println(Thread.currentThread().getName() + " Athletes , Start running ");
                    TimeUnit.SECONDS.sleep(current);
                } catch (InterruptedException | BrokenBarrierException e) {
                    e.printStackTrace();
                }
            });
        }
        executorService.shutdown();
    }
}

unit testing

publicclass CyclicBarrierDemoTest {

    @Test
    public void testRun() throws InterruptedException {
        CyclicBarrier cyclicBarrier = new CyclicBarrier(4, () -> System.out.println(" All athletes are ready , The referee ordered ..."));
        CyclicBarrierDemo cyclicBarrierDemo = new CyclicBarrierDemo(cyclicBarrier);
        cyclicBarrierDemo.startRun();
        Thread.currentThread().join();
    }
}

3. CountDownLatch And CyclicBarrier Comparison

CountDownLatch And CyclicBarrier Are used to control concurrency tool class , Can be understood as maintenance is a counter , But the two still have different emphases :

  1. CountDownLatch Generally used for a thread A Wait for a number of other threads to complete the task , It only executes. ; and CyclicBarrier It is generally used for a group of threads to wait for each other to a certain state , Then this set of threads executes simultaneously ;CountDownLatch Emphasize that one thread and more than one thread finish something .CyclicBarrier It's multiple threads waiting for each other , When everyone has finished , Let's go hand in hand again .

  2. call CountDownLatch Of countDown After the method , The current thread does not block , Will continue to carry on ; And call CyclicBarrier Of await Method , Will block the current thread , until CyclicBarrier When all the specified threads have reached the specified point , To carry on ;

  3. CountDownLatch There are fewer methods , Simple operation , and CyclicBarrier There are more ways to offer , For example, through getNumberWaiting(),isBroken() These methods get the current state of multiple threads , also CyclicBarrier Can be passed in barrierAction, Specifies the business function to execute when all threads arrive ;

  4. CountDownLatch It can't be reused , and CyclicLatch It can be reused .

4. summary

CountDownLatch and CyclicBarrier yes Java And two very easy to use thread synchronization tool classes provided by the contract , The difference between the usage of these two tool classes needs to be emphasized here :

CountDownLatch It is mainly used to solve the scenario where one thread waits for multiple threads , It can be analogized that the head of a tour group has to wait for all the tourists to arrive before going to the next scenic spot ;

and CyclicBarrier It's a group of threads waiting for each other , It's more like a couple of friends who never give up . besides CountDownLatch The counter of can't be recycled , That is to say, once the counter is reduced to 0, Another thread call await(), The thread will go directly through .

but CyclicBarrier The counter of is recyclable , And it has the function of automatic reset , Once the counter goes down to 0 It will automatically reset to the initial value you set . besides ,CyclicBarrier You can also set the callback function , It can be said that it has rich functions .

0e827cfdc06e2d3baeec32135e137278.gif

原网站

版权声明
本文为[Ma Nong, little fat brother]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/188/202207071744356202.html