CountDownLatch
位於java.util.concurrent
包下,利用它能夠實現相似計數器的功能。好比有一個任務A,它要等到其它3任務完成才能執行,此時就能夠用CountDownLatch
來實現。
假設計數器的值爲2,線程A調用await()
方法以後,A線程就進入了等待狀態,以後其它線程中執行countDown()
,計數器就會-1,該操做線程繼續執行,當計數器從2編程0,線程A繼續執行。
package com.keytech.task; import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; import java.util.concurrent.CountDownLatch; import java.util.concurrent.Executor; import java.util.concurrent.Executors; class TaskApplicationTests { //目標:炒菜 //1.洗菜 5秒 //2.買鹽 3秒 public static void main(String[] args) throws InterruptedException { Executor executor=Executors.newFixedThreadPool(2); CountDownLatch countDownLatch=new CountDownLatch(2); long now = System.currentTimeMillis(); //洗菜5秒 executor.execute(()->{ try{ Thread.sleep(5000); }catch (Exception e){ e.printStackTrace(); }finally { if(countDownLatch!=null){ countDownLatch.countDown(); } } }); //買鹽3秒 executor.execute(()->{ try{ Thread.sleep(3000); }catch (Exception e){ e.printStackTrace(); }finally { if(countDownLatch!=null){ countDownLatch.countDown(); } } }); countDownLatch.await(); System.out.println("能夠炒菜了"+(System.currentTimeMillis()-now)); } }
//能夠炒菜了5082java
Semaphore
就是信號量,Semaphore
能夠阻塞線程而且能夠控制同時訪問線程的個數,經過acquire()
獲取一個許可,若是沒有獲取到就繼續等待,經過release()
釋放一個許可。Semaphore
和鎖有點相似,均可以控制對某個資源的訪問權限。
CountDownLatch
和Semaphore
一般和線程池配合使用。Semaphore適合控制併發數,CountDownLatch比較適合保證線程執行完後再執行其餘處理,所以模擬併發時,使用二者結合起來是最好的。springSemaphore能夠用來作流量分流,特別是對公共資源有限的場景,好比數據庫鏈接。
假設有這個的需求,讀取幾萬個文件的數據到數據庫中,因爲文件讀取是IO密集型任務,能夠啓動幾十個線程併發讀取,可是數據庫鏈接數只有10個,這時就必須控制最多隻有10個線程可以拿到數據庫鏈接進行操做。這個時候,就可使用Semaphore作流量控制。數據庫
package com.keytech.task; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Semaphore; /** * @className: SemaphoreTest * @description: TODO 類描述 * @author: mac * @date: 2020/12/26 **/ public class SemaphoreTest { public static void main(String[] args) { ExecutorService executor=Executors.newFixedThreadPool(40); Semaphore semaphore=new Semaphore(10); for (int i = 0; i < 40; i++) { executor.execute(()->{ try { semaphore.acquire(); System.out.println("處理數據中......"); Thread.sleep(3000); semaphore.release(); } catch (InterruptedException e) { e.printStackTrace(); } }); } executor.shutdown(); } }