1. 程式人生 > >Java併發基礎:CountDownLatch和CyclicBarrier

Java併發基礎:CountDownLatch和CyclicBarrier

CountDownLatch概括

CountDownLatch能夠使一個執行緒在等待其他一個或多個執行緒執行結束之後,再繼續執行。

使用一個計數器進行實現。計數器初始值為執行緒的數量。當每一個執行緒完成自己任務後,計數器的值就會減一。當計數器的值為0時,表示所有的執行緒都已經完成了任務,然後在CountDownLatch上等待的執行緒就可以恢復執行任務。

CountDownLatch用法

例子:假設現在有t1,t2,t3三個執行緒,保證t3執行緒在t1和t2都執行完成後再執行

package org.cc;

import java.util.Random;
import java.util.concurrent.CountDownLatch;

public class UseCountDownLatch {
    public static void main(String[] args) {
        //CountDownLatch(int count)
        //count如果是2就代表cdl.countDown()兩次 cdl.await()所在的執行緒才能被喚醒
        CountDownLatch cdl=new CountDownLatch(2);
        new Thread(()->{
            System.out.println("進入t1執行緒......");

            try {
                //隨機休息1到10秒用來摸你程式執行
                Thread.sleep(1000*(new Random().nextInt(10)));
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("t1執行緒執行結束......");
            //cdl.countDown()一次
            cdl.countDown();
        }).start();
        new Thread(()->{
            System.out.println("進入t2執行緒......");

            try {
                //隨機休息1到10秒用來摸你程式執行
                Thread.sleep(1000*(new Random().nextInt(10)));
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("t2執行緒執行結束......");
            //cdl.countDown()兩次
            cdl.countDown();
        }).start();
        new Thread(()->{
            System.out.println("進入t3執行緒......");
            try {
                cdl.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            try {
                //隨機休息1到10秒用來摸你程式執行
                Thread.sleep(1000*(new Random().nextInt(10)));
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("t3執行緒執行結束......");
            cdl.countDown();
        }).start();

    }
}
進入t1執行緒......
進入t3執行緒......
進入t2執行緒......
t1執行緒執行結束......
t2執行緒執行結束......
t3執行緒執行結束......

CyclicBarrier概括

多執行緒的進行阻塞,等待某一個臨界值條件滿足後,同時執行!

CyclicBarrier用法

例子:假設用三個運動員。等3個運動員都準備好之後同時開始起跑;

package org.cc;

import java.util.Random;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class UseCyclicBarrier {
    static class Runner implements Runnable {
        private String name;
        private CyclicBarrier cyclic;

        public Runner(String name, CyclicBarrier cyclic) {
            this.name = name;
            this.cyclic = cyclic;
        }

        @Override
        public void run() {
            System.out.println("運動員" + name + "進入賽道,準備中.....");

            try {
                //隨機休息1到10秒用來摸你程式執行
                Thread.sleep(1000 * (new Random().nextInt(10)));
                System.out.println("運動員" + name + "準備結束,等待起跑訊號!!!!");
                cyclic.await();
            } catch (Exception e) {
                e.printStackTrace();
            }

            System.out.println("運動員" + name + "起跑!!!!");
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public CyclicBarrier getCyclic() {
            return cyclic;
        }

        public void setCyclic(CyclicBarrier cyclic) {
            this.cyclic = cyclic;
        }
    }

    public static void main(String[] args) {

        //3代表執行了3次cyclic.await()後結束等待
        //此處是代表3個運動員準備好了之後開始起跑
        CyclicBarrier c = new CyclicBarrier(3);
        ExecutorService s = Executors.newFixedThreadPool(3);
        s.submit(new Runner("張三", c));
        s.submit(new Runner("李四", c));
        s.submit(new Runner("王五", c));
        s.shutdown();
    }
}
運動員李四進入賽道,準備中.....
運動員王五進入賽道,準備中.....
運動員張三進入賽道,準備中.....
運動員李四準備結束,等待起跑訊號!!!!
運動員王五準備結束,等待起跑訊號!!!!
運動員張三準備結束,等待起跑訊號!!!!
運動員王五起跑!!!!
運動員李四起跑!!!!
運動員張三起跑!!!!

CyclicBarrier和CountDownLatch的區別

 假設一共有N個執行緒,CountDownLatch是一個執行緒等待其他N-1個執行緒執行結束後再執行,CyclicBarrier是N個執行緒都準備就緒後同時執行。

CountDownLatch是減計數方式,而CyclicBarrier是加計數方式。