多線程CyclicBarrier與CountDownLatch使用示例

多線程最典型的需求場景通常是:有的時候爲了獲取性能,須要各個業務並行獲取並處理數據,同時返回處理好的數據,這時候多線程就派上用處了。java

對這個場景,最簡單的代碼實現是能夠使用CyclicBarrier或CountDownLatch;多線程

話很少說,直接上代碼:ide

 測試主類-MainThread:性能

import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.CyclicBarrier;

/**
 * shiroexample
 * functional describe:
 *
 * @author DR.YangLong [410357434@163.com]
 * @version 1.0 2015/4/13 9:22
 */
public class MainThread extends Thread{
    private Map<String,Object> resultMap;

    public MainThread(Map<String, Object> resultMap) {
        this.resultMap = resultMap;
    }

    @Override
    public void run() {
        System.out.println("實驗2到主線程了,取出結果:");
        Iterator<String> iterator=resultMap.keySet().iterator();
        while (iterator.hasNext()){
            String name=iterator.next();
            System.out.println("線程:" + resultMap.get(name));
        }
        System.out.println("實驗2等待線程結束。");
    }

    public static void main(String[] args){
        /***
         * 障礙器測試
         */
        Map<String,Object> resultMap=new ConcurrentHashMap<String, Object>(6);
        CyclicBarrier cyclicBarrier=new CyclicBarrier(5);//實驗1:主線等待其餘線程
        //CyclicBarrier cyclicBarrier=new CyclicBarrier(4,new MainThread(resultMap));//實:2:通常性並行其餘線程執行完執行某個線程。
        new ThreadService("CyclicBarrier服務1",cyclicBarrier,resultMap).start();
        new ThreadService("CyclicBarrier服務2",cyclicBarrier,resultMap).start();
        new ThreadService("CyclicBarrier服務3",cyclicBarrier,resultMap).start();
        new ThreadService("CyclicBarrier服務4",cyclicBarrier,resultMap).start();
        //如下爲實驗1內容,實驗2時註釋掉
        try {
            System.out.println("當前線程等待其餘線程");
            cyclicBarrier.await();
            System.out.println("當前等待結束,開始執行,取出結果:");
            Iterator<String> iterator=resultMap.keySet().iterator();
            while (iterator.hasNext()){
                String name=iterator.next();
                System.out.println("線程:" + resultMap.get(name));
            }
            System.out.println("當前線結束。");
        } catch (Exception e) {
            e.printStackTrace();
        }

        /***
         * 計數數器測試
         */
        resultMap.clear();
        CountDownLatch countDownLatch=new CountDownLatch(4);
        new CountDownService("CountDownLatch服務A",countDownLatch,resultMap).start();
        new CountDownService("CountDownLatch服務B",countDownLatch,resultMap).start();
        new CountDownService("CountDownLatch服務C",countDownLatch,resultMap).start();
        new CountDownService("CountDownLatch服務D",countDownLatch,resultMap).start();
        try {
            System.out.println("CountDownLatch當前線程等待。");
            countDownLatch.await();//等待並行線程完成工做
            System.out.println("CountDownLatch當前線程等待結束,開始執行,取出結果:");
            Iterator<String> iterator=resultMap.keySet().iterator();
            while (iterator.hasNext()){
                String name=iterator.next();
                System.out.println("線程:" + resultMap.get(name));
            }
            System.out.println("CountDownLatch當前線程結束。");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

    CyclicBarrier 測試使用的service,ThreadService:測試

import java.util.Map;
import java.util.concurrent.CyclicBarrier;

/**
 * shiroexample
 * functional describe:
 *
 * @author DR.YangLong [410357434@163.com]
 * @version 1.0 2015/4/13 9:12
 */
public class ThreadService extends Thread{
    private String name;
    private CyclicBarrier cyclicBarrier;
    private Map<String,Object> resultMap;

    public ThreadService(String name, CyclicBarrier cyclicBarrier,Map<String,Object> resultMap) {
        this.name = name;
        this.cyclicBarrier = cyclicBarrier;
        this.resultMap=resultMap;
    }

    @Override
    public void run() {
        System.out.println("子線程"+this.name+"正在執行!");
        try {
            resultMap.put(this.name,this.name);
            Thread.sleep(1000);
            System.out.println("子線程"+this.name+"執行完成!");
            cyclicBarrier.await();//計數器-1
          //添加日誌等操做在下面,當計數器爲0時執行
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}


CountDownLatch 測試使用Service CountDownService:this

import java.util.Map;
import java.util.concurrent.CountDownLatch;

/**
 * shiroexample
 * functional describe:
 *
 * @author DR.YangLong [410357434@163.com]
 * @version 1.0 2015/4/13 10:01
 */
public class CountDownService extends Thread{
    private String name;
    private CountDownLatch countDownLatch;
    private Map<String,Object> resultMap;

    public CountDownService(String name, CountDownLatch countDownLatch,Map<String,Object> resultMap) {
        this.name = name;
        this.countDownLatch = countDownLatch;
        this.resultMap=resultMap;
    }

    @Override
    public void run() {
        System.out.println("子線程" + this.name + "正在執行!");
        try {
            resultMap.put(this.name,this.name);
            Thread.sleep(1000);
            System.out.println("子線程"+this.name+"執行完成!");
            countDownLatch.countDown();//計數器-1
            //添加日誌等操做在下面,當計數器爲0時執行
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

運行結果:spa

當前線程等待其餘線程
子線程CyclicBarrier服務1正在執行!
子線程CyclicBarrier服務2正在執行!
子線程CyclicBarrier服務3正在執行!
子線程CyclicBarrier服務4正在執行!
子線程CyclicBarrier服務1執行完成!
子線程CyclicBarrier服務4執行完成!
子線程CyclicBarrier服務3執行完成!
子線程CyclicBarrier服務2執行完成!
當前等待結束,開始執行,取出結果:
線程:CyclicBarrier服務4
線程:CyclicBarrier服務1
線程:CyclicBarrier服務3
線程:CyclicBarrier服務2
當前線結束。
CyclicBarrier服務1日誌處理......
CyclicBarrier服務4日誌處理......
CyclicBarrier服務3日誌處理......
CyclicBarrier服務2日誌處理......
CountDownLatch當前線程等待。
子線程CountDownLatch服務A正在執行!
子線程CountDownLatch服務B正在執行!
子線程CountDownLatch服務C正在執行!
子線程CountDownLatch服務D正在執行!
子線程CountDownLatch服務A執行完成!
子線程CountDownLatch服務B執行完成!
CountDownLatch服務A日誌處理......
CountDownLatch服務B日誌處理......
子線程CountDownLatch服務D執行完成!
CountDownLatch服務D日誌處理......
子線程CountDownLatch服務C執行完成!
CountDownLatch服務C日誌處理......
CountDownLatch當前線程等待結束,開始執行,取出結果:
線程:CountDownLatch服務A
線程:CountDownLatch服務D
線程:CountDownLatch服務B
線程:CountDownLatch服務C
CountDownLatch當前線程結束。

  對於數據的取回,有2個方式,一個是使用單例的容器,另一個是定義成屬性,提供getter方法,運行完成後調用獲取,但這又涉及到這2者的區別:
線程

CyclicBarrier 阻塞全部調用await()的線程,等待計數器爲0,全部線程【包括一個目標線程】才所有一塊兒往下執行。
日誌

CountDownLatch 不阻塞全部線程【countDown()的線程不會被阻塞】,只阻塞調用await()的線程,當計數器爲0時調用await()的線程繼續往下執行。code

因此,須要返回值在線程阻塞前完成封裝,以確保主線程可以得到已完成封裝的返回值。

相關文章
相關標籤/搜索