1. 程式人生 > >java併發包-CountDownLatch CyclicBarrier Semaphore 案例

java併發包-CountDownLatch CyclicBarrier Semaphore 案例

1.CountDownLatch案例

        --呼叫.await()阻塞等待

        --呼叫countDown()方法每次遞減1,直到為0,啟動所有等待的執行緒

package com.roger.juc;

import java.util.concurrent.CountDownLatch;

/**
 * java併發包-CountDownLatch計數器
 * <p>
 * 一個裁判
 * 五個運動員
 * 裁判需要等到所有的運動員都就位了,才能下達起跑的指令
 * 等所有的運動員全都完成所跑賽程,才能下達結束指令
 */
public class CountDownLatchMain {

    public static void main(String[] args) throws Exception{
        int num = 5;
        CountDownLatch sportLatch = new CountDownLatch(1);
        CountDownLatch judgeLatch = new CountDownLatch(num);
        for (int i = 1; i <= num; i++) {
            new Thread(new Sporter(sportLatch,judgeLatch,String.valueOf(i))).start();
        }
        Thread.sleep(100);
        System.out.println("所有的運動員已就緒");
        System.out.println("裁判下達起跑指令");
        sportLatch.countDown();
        System.out.println("裁判下達起跑指令後,等待所有運動員跑完全程");
        judgeLatch.await();
        System.out.println("所有運動員跑完全程.");
        System.out.println("比賽結束,裁判統計運動員的成績.");
    }

    static class Sporter implements Runnable {

        private CountDownLatch sportLatch;
        private CountDownLatch judgeLatch;
        private String name;

        public Sporter(CountDownLatch sportLatch, CountDownLatch judgeLatch, String name) {
            this.sportLatch = sportLatch;
            this.judgeLatch = judgeLatch;
            this.name = name;
        }

        @Override
        public void run() {
            System.out.println("運動員" + name + "已就緒...");
            try {
                sportLatch.await();
                Thread.sleep((long) (Math.random()*10000));
            }catch (InterruptedException e){

            }finally {
                System.out.println("運動員" + name + "已到達目的地...");
                judgeLatch.countDown();
                System.out.println("裁判記錄運動員" + name + "的成績");
            }
        }
    }
}

某一次執行結果:

運動員1已就緒...
運動員3已就緒...
運動員5已就緒...
運動員2已就緒...
運動員4已就緒...
所有的運動員已就緒
裁判下達起跑指令
裁判下達起跑指令後,等待所有運動員跑完全程
運動員3已到達目的地...
裁判記錄運動員3的成績
運動員4已到達目的地...
裁判記錄運動員4的成績
運動員5已到達目的地...
裁判記錄運動員5的成績
運動員1已到達目的地...
裁判記錄運動員1的成績
運動員2已到達目的地...
裁判記錄運動員2的成績
所有運動員跑完全程.
比賽結束,裁判統計運動員的成績.

2.CyclicBarrier案例

    --呼叫await()方法每次遞增1,直到達到某個臨界值,才能執行下一個任務

    --呼叫reset()方法重置,從臨界值回到起點,迴圈使用

package com.roger.juc;

import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;

/**
 * 5個生死兄弟,相約去喝酒,並約定只有等到所有的兄弟都到齊,
 * 才可以開喝,不然要一直等待
 */
public class CyclicBarrierMain {

    public static void main(String[] args) {
        int num = 5;
        CyclicBarrier cyclicBarrier = new CyclicBarrier(num, new Runnable() {
            @Override
            public void run() {
                System.out.println("所有兄弟已到達");
                System.out.println("開喝....");
            }
        });

        for (int i = 1; i <= num; i++) {
            new Thread(new Brother(cyclicBarrier, String.valueOf(i))).start();
        }

    }

    static class Brother implements Runnable {

        private CyclicBarrier cyclicBarrier;
        private String name;

        public Brother(CyclicBarrier cyclicBarrier, String name) {
            this.cyclicBarrier = cyclicBarrier;
            this.name = name;
        }

        @Override
        public void run() {
            try {
                Thread.sleep((long) (Math.random() * 10000));
                System.out.println("兄弟" + name + "到達...");
                cyclicBarrier.await();
            } catch (InterruptedException e) {

            } catch (BrokenBarrierException e) {

            }
        }
    }
}

 某次的允許結果:

兄弟3到達...
兄弟2到達...
兄弟5到達...
兄弟1到達...
兄弟4到達...
所有兄弟已到達
開喝....

3.Semaphore 案例

package com.roger.juc;

import java.util.concurrent.Semaphore;

/**
 * 一個廁所只有3個坑位,但是有10個人來上廁所,那怎麼辦?
 * 假設10的人的編號分別為1-10,並且1號先到廁所,10號最後到廁所。
 * 那麼1-3號來的時候必然有可用坑位,順利如廁,
 * 4號來的時候需要看看前面3人是否有人出來了,如果有人出來,進去,否則等待。
 * 同樣的道理,4-10號也需要等待正在上廁所的人出來後才能進去,
 * 並且誰先進去這得看等待的人是否有素質,是否能遵守先來先上的規則。
 */
public class SemaphoreMain {

    public static void main(String[] args) {
        int pepoleNum = 10;
        //測試只有3個坑位
        Semaphore toiletCount = new Semaphore(3);
        for (int i = 1; i <= pepoleNum; i++) {
            new Thread(new Toilet(String.valueOf(i),toiletCount)).start();
        }
    }

    static class Toilet implements Runnable {

        private String name;
        private Semaphore toiletCount;

        public Toilet(String name, Semaphore semaphore) {
            this.name = name;
            this.toiletCount = semaphore;
        }

        @Override
        public void run() {
            int availablePermits = toiletCount.availablePermits();
            if (availablePermits > 0) {
                System.out.println("廁所有坑位");
            }else{
                System.out.println(name + "等待...");
            }

            try {
                //申請資源
                toiletCount.acquire();
                System.out.println(name + "上廁所....");
                Thread.sleep((long) (Math.random() * 10000));

            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                System.out.println(name + "上完廁所....");
                //釋放資源
                toiletCount.release();
            }
        }
    }
}

某一次的允許結果

廁所有坑位
1上廁所....
廁所有坑位
2上廁所....
廁所有坑位
5上廁所....
4等待...
8等待...
10等待...
3等待...
9等待...
6等待...
7等待...
1上完廁所....
4上廁所....
5上完廁所....
8上廁所....
2上完廁所....
10上廁所....
4上完廁所....
3上廁所....
8上完廁所....
9上廁所....
3上完廁所....
6上廁所....
9上完廁所....
7上廁所....
10上完廁所....
7上完廁所....
6上完廁所....