歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux編程 >> Linux編程

Java多線程-CyclicBarrier

介紹

一個同步輔助類,它允許一組線程互相等待,直到到達某個公共屏障點 (common barrier point)。在涉及一組固定大小的線程的程序中,這些線程必須不時地互相等待,此時 CyclicBarrier 很有用。因為該 barrier 在釋放等待線程後可以重用,所以稱它為循環 的 barrier。

CyclicBarrier 支持一個可選的 Runnable 命令,在一組線程中的最後一個線程到達之後(但在釋放所有線程之前),該命令只在每個屏障點運行一次。若在繼續所有參與線程之前更新共享狀態,此屏障操作 很有用。

主要方法

//設置parties、count及barrierCommand屬性。 
CyclicBarrier(int): 
//當await的數量到達了設定的數量後,首先執行該Runnable對象。 
CyclicBarrier(int,Runnable): 
//通知barrier已完成線程 
await():

應用場景

1:CyclicBarrier 表示大家彼此等待,大家集合好後才開始出發,分散活動後又在i指定地點集合碰面,這就好比整個公司的人員利用周末時間集體郊游一樣,先各自從家出發到公司集合後,再同時出發到公園游玩,在指定地點集合後再同時開始就餐。

代碼:

public class CyclicBarrierTest {
    public static void main(String[] args){
        ExecutorService pool = Executors.newCachedThreadPool();
        final CyclicBarrier cyclicBarrier = new CyclicBarrier(3);
       
        for (int i = 0; i < 3; i++) {
            Runnable runnable = new Runnable() {
                @Override
                public void run(){
                    try {
                        Thread.sleep(new Random().nextInt(5000));
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName()+"到達地點一,當前等待人數為"+(cyclicBarrier.getNumberWaiting()+1)+(cyclicBarrier.getNumberWaiting()+1==3?"繼續出發":"繼續等待"));
                    try {
                        cyclicBarrier.await();//障礙等待點
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    } catch (BrokenBarrierException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                    try {
                        Thread.sleep(new Random().nextInt(5000));
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName()+"到達地點二,當前等待人數為"+(cyclicBarrier.getNumberWaiting()+1)+(cyclicBarrier.getNumberWaiting()+1==3?"繼續出發":"繼續等待"));
                    try {
                        cyclicBarrier.await();//障礙等待點
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    } catch (BrokenBarrierException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                    try {
                        Thread.sleep(new Random().nextInt(5000));
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName()+"到達地點三,當前等待人數為"+(cyclicBarrier.getNumberWaiting()+1)+(cyclicBarrier.getNumberWaiting()+1==3?"人齊了出發":"繼續等待"));
                    try {
                        cyclicBarrier.await();//障礙等待點
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    } catch (BrokenBarrierException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
            };
            pool.execute(runnable);
        }
        pool.shutdown();
    }
}

執行結果:

pool-1-thread-3到達地點一,當前等待人數為1繼續等待
pool-1-thread-1到達地點一,當前等待人數為2繼續等待
pool-1-thread-2到達地點一,當前等待人數為3繼續出發
pool-1-thread-1到達地點二,當前等待人數為1繼續等待
pool-1-thread-3到達地點二,當前等待人數為2繼續等待
pool-1-thread-2到達地點二,當前等待人數為3繼續出發
pool-1-thread-3到達地點三,當前等待人數為1繼續等待
pool-1-thread-2到達地點三,當前等待人數為2繼續等待
pool-1-thread-1到達地點三,當前等待人數為3人齊了出發

2:在某種需求中,比如一個大型的任務,常常需要分配好多子任務去執行,只有當所有子任務都執行完成時候,才能執行主任務,這時候,就可以選擇CyclicBarrier了。

代碼:

public class CyclicBarrierTest1 {
    public static void main(String[] args) {
        ExecutorService threadPool = Executors.newCachedThreadPool();
        CyclicBarrier barrier = new CyclicBarrier(5, new mainTask());
        for (int i = 0; i < 5; i++) {
            subTask subTask = new subTask(barrier);
            threadPool.execute(subTask);
        }
        threadPool.shutdown();
    }
}

class subTask implements Runnable{
    private CyclicBarrier barrier;
   
    public subTask(CyclicBarrier barrier) {
        super();
        this.barrier = barrier;
    }
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName()+"正在執行");
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName()+"執行完畢,等待其他結果");
        try {
            barrier.await();
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (BrokenBarrierException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
       
    }
}
class mainTask implements Runnable{

    @Override
    public void run() {
        System.out.println("總任務執行完畢");
    }
   
}

執行結果:

pool-1-thread-2正在執行
pool-1-thread-3正在執行
pool-1-thread-1正在執行
pool-1-thread-4正在執行
pool-1-thread-5正在執行
pool-1-thread-2執行完畢,等待其他結果
pool-1-thread-5執行完畢,等待其他結果
pool-1-thread-1執行完畢,等待其他結果
pool-1-thread-4執行完畢,等待其他結果
pool-1-thread-3執行完畢,等待其他結果
總任務執行完畢

另外,CyclicBarrier是可以重用的,它可以在使用完後繼續使用,這就是Cyclic(循環)的意思。

Copyright © Linux教程網 All Rights Reserved