多線程最典型的需求場景通常是:有的時候爲了獲取性能,須要各個業務並行獲取並處理數據,同時返回處理好的數據,這時候多線程就派上用處了。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
因此,須要返回值在線程阻塞前完成封裝,以確保主線程可以得到已完成封裝的返回值。