這主要想寫一下Java中的jdk提供的一些線程中的工具,java
1、semaphore信號燈併發
Semaphore能夠維護當前訪問自身的線程個數,並提供了同步機制,使用Semaphore能夠控制同時訪問資源的線程的個數。例如,實現一個文件容許訪問的併發數。dom
Semaphore實現的功能就相似廁所5個坑,假若有10我的要上廁所,那麼同時能夠有多少人上廁所呢?同時只能有5我的可以佔用,當5我的中的任何一個讓開後,其中在等待的另外5箇中的一個就能夠佔用了。ide
單個信號量的Semaphore對象能夠實現互斥鎖的功能,而且能夠是由一個線程得到了「鎖」,再由另外一個線程釋放「鎖」,這可應用於死鎖恢復的一些場合。工具
代碼以下:測試
1 import java.util.concurrent.ExecutorService; 2 import java.util.concurrent.Executors; 3 import java.util.concurrent.Semaphore; 4 5 /** 6 * @className: SemaphoreTest 7 * @description: Semaphore信號燈測試實例 8 * @author: ssc 9 * @date: 2019年6月18日 下午9:01:33 10 */ 11 public class SemaphoreTest { 12 13 public static void main(String[] args) { 14 15 ExecutorService services = Executors.newCachedThreadPool(); 16 Semaphore sp = new Semaphore(3); 17 18 for (int i = 0; i < 10; i++) { 19 Runnable runnable = new Runnable() { 20 @Override 21 public void run() { 22 try { 23 // 查詢信號燈的狀態 是否能夠進入 24 sp.acquire(); 25 System.out.println("線程 " + Thread.currentThread().getName() + "進入,當前已有" 26 + (3 - sp.availablePermits()) + " 併發"); 27 Thread.sleep((long) (Math.random() * 10000)); 28 System.out.println("線程 " + Thread.currentThread().getName() + " 即將離開"); 29 // 釋放信號燈 讓別的線程進入 30 sp.release(); 31 System.out.println("線程 " + Thread.currentThread().getName() + "已離開,當前已有" 32 + (3 - sp.availablePermits()) + " 併發"); 33 } catch (Exception e) { 34 e.printStackTrace(); 35 } 36 } 37 }; 38 services.execute(runnable); 39 } 40 } 41 42 }
2、CyclicBarrier循環路障ui
字面意思迴環柵欄,經過它能夠實現讓一組線程等待至某個狀態以後再所有同時執行。叫作迴環是由於當全部等待線程都被釋放之後,CyclicBarrier能夠被重用。咱們暫且把這個狀態就叫作barrier,當調用await()方法以後,線程就處於barrier了。spa
使用代碼以下:線程
1 import java.util.concurrent.CyclicBarrier; 2 import java.util.concurrent.ExecutorService; 3 import java.util.concurrent.Executors; 4 5 /** 6 * @className: CyclicBarrier 7 * @description: 線程中的循環路障工具類 8 * @author: ssc 9 * @date: 2019年6月18日 下午9:58:36 10 */ 11 public class CyclicBarrierTest { 12 13 public static void main(String[] args) { 14 ExecutorService services = Executors.newCachedThreadPool(); 15 // 建立 路障實例對象 16 CyclicBarrier cb = new CyclicBarrier(3); 17 18 for (int i = 0; i < 3; i++) { 19 Runnable runnable = new Runnable() { 20 @Override 21 public void run() { 22 try { 23 24 Thread.sleep((long) Math.random() * 10000); 25 System.out.println("線程 " + Thread.currentThread().getName() + "即將到達集合地點1,當前已有" 26 + (cb.getNumberWaiting()) + " 到達,正在等候..."); 27 // 到此若是沒有達到公共屏障點,則該線程處於等待狀態,若是達到公共屏障點則全部處於等待的線程都繼續往下運行 28 cb.await(); 29 30 Thread.sleep((long) Math.random() * 10000); 31 System.out.println("線程 " + Thread.currentThread().getName() + "即將到達集合地點2,當前已有" 32 + (cb.getNumberWaiting()) + " 到達,正在等候..."); 33 cb.await(); 34 35 Thread.sleep((long) Math.random() * 10000); 36 System.out.println("線程 " + Thread.currentThread().getName() + "即將到達集合地點3,當前已有" 37 + (cb.getNumberWaiting()) + " 都到齊了, 繼續走啊!"); 38 cb.await(); 39 40 } catch (Exception e) { 41 e.printStackTrace(); 42 } 43 } 44 }; 45 services.execute(runnable); 46 } 47 services.shutdown(); 48 } 49 50 }
3、CountDownLatch倒計時計時器code
CountDownLatch猶如倒計時計時器,調用CountDownLatch對象的countDown方法就將計時器減去1。當計時器到達0時,則全部等待着或者單個等待着開始執行。
能夠實現一我的或者是多我的等待其餘人通知他,能夠實現一我的通知多我的的效果。相似裁判一聲口令,運動員同時開始奔跑,或者全部運動員都跑到終點後裁判才能夠通知結果。還能夠實現一個計劃須要多個領導簽字後才能夠繼續向下實施的狀況
示例代碼以下:
1 import java.util.concurrent.CountDownLatch; 2 import java.util.concurrent.ExecutorService; 3 import java.util.concurrent.Executors; 4 5 /** 6 * @className: CountDownLatchTest 7 * @description: 線程中的計時器類 8 * @author: ssc 9 * @date: 2019年6月20日 下午9:13:40 10 */ 11 public class CountDownLatchTest { 12 13 public static void main(String[] args) { 14 ExecutorService services = Executors.newCachedThreadPool(); 15 // 主線程中的計時器 至關於賽跑中的裁判 16 CountDownLatch cdOrder = new CountDownLatch(1); 17 // 新建線程的計時器 至關於賽跑中的運動員 18 CountDownLatch cdAnswer = new CountDownLatch(3); 19 20 for (int i = 0; i < 3; i++) { 21 Runnable runnable = new Runnable() { 22 @Override 23 public void run() { 24 try { 25 System.out.println("線程 " + Thread.currentThread().getName() + "正準備接受命令..."); 26 // 等待計時器上技數值 歸0 纔開始執行 至關於運動員等待裁判的起跑槍聲 27 cdOrder.await(); 28 System.out.println("線程 " + Thread.currentThread().getName() + "已經接受命令..."); 29 Thread.sleep((long) (Math.random() * 10000)); 30 System.out.println("線程 " + Thread.currentThread().getName() + "等待命令處理結果..."); 31 // 計時器上的數值減去1 至關於運動員相繼跑到終點 等待裁判宣佈最終結果 32 cdAnswer.countDown(); 33 } catch (Exception e) { 34 // TODO Auto-generated catch block 35 e.printStackTrace(); 36 } 37 } 38 }; 39 services.execute(runnable); 40 } 41 services.shutdown(); 42 43 try { 44 Thread.sleep((long) (Math.random() * 10000)); 45 System.out.println("線程 " + Thread.currentThread().getName() + "即將發佈命令..."); 46 // 計數器上的 技數的值減去1 這個計數器自己就是 1 就至關於裁判的起跑槍聲,只有這個計時器到0,其餘線程纔開始執行 47 cdOrder.countDown(); 48 System.out.println("線程 " + Thread.currentThread().getName() + "已經發布命令,正在等待結果..."); 49 // 只有另外三個線程都執行到這裏,分別將計時器的數值減去1,下面的代碼才執行,至關於裁判等運動員都經過終點,才宣佈結果 50 cdAnswer.await(); 51 System.out.println("線程 " + Thread.currentThread().getName() + "已收到全部響應結果..."); 52 } catch (Exception e) { 53 e.printStackTrace(); 54 } 55 } 56 }
4、Exchanger工具類
用於實現兩我的之間的數據交換,每一個人在完成一件事物後,想與對方交換數據,第一個拿出數據的人將一直等待第二我的拿出數據來時,纔會互相交換
示例代碼以下:
1 import java.util.concurrent.Exchanger; 2 import java.util.concurrent.ExecutorService; 3 import java.util.concurrent.Executors; 4 5 /** 6 * @className: ExchangerTest 7 * @description: Exchanger工具類的示例 8 * @author: ssc 9 * @date: 2019年6月20日 下午10:00:19 10 */ 11 public class ExchangerTest { 12 13 public static void main(String[] args) { 14 ExecutorService services = Executors.newCachedThreadPool(); 15 16 Exchanger exchanger = new Exchanger(); 17 18 services.execute(new Runnable() { 19 @Override 20 public void run() { 21 try { 22 String data1 = "abc"; 23 System.out.println("線程" + Thread.currentThread().getName() + "正準備把數據" + data1 + "換出去"); 24 Thread.sleep((long) (Math.random() * 10000)); 25 // 進行數據的交換 26 String data2 = (String) exchanger.exchange(data1); 27 System.out.println("線程" + Thread.currentThread().getName() + "換回的數據是" + data2); 28 } catch (InterruptedException e) { 29 // TODO Auto-generated catch block 30 e.printStackTrace(); 31 } 32 } 33 }); 34 35 services.execute(new Runnable() { 36 @Override 37 public void run() { 38 try { 39 String data1 = "edf"; 40 System.out.println("線程" + Thread.currentThread().getName() + "正準備把數據" + data1 + "換出去"); 41 Thread.sleep((long) (Math.random() * 10000)); 42 // 進行數據的交換 43 String data2 = (String) exchanger.exchange(data1); 44 System.out.println("線程" + Thread.currentThread().getName() + "換回的數據是" + data2); 45 } catch (InterruptedException e) { 46 // TODO Auto-generated catch block 47 e.printStackTrace(); 48 } 49 } 50 }); 51 services.shutdown(); 52 } 53 }