java并發(fā)包中CountDownLatch和線程池的使用詳解
1.CountDownLatch
現(xiàn)在做的這個(gè)華為云TaurusDB比賽中,參考的之前參加過阿里的PolarDB大賽的兩個(gè)大佬的代碼,發(fā)現(xiàn)都有用到CountDownLatch這個(gè)類,之前看代碼的時(shí)候也看過,但是沒有搞得很明白,自己寫也寫不出來(lái),在此自己先學(xué)習(xí)一下。
字面理解:CountDownLatch:數(shù)量減少的門栓。
創(chuàng)建這樣一個(gè)門栓
CountDownLatch countDownLatch = new CountDownLatch(count);
參數(shù):count,門栓的計(jì)數(shù)次數(shù)。
在所有線程執(zhí)行完成之前,調(diào)用countDownLatch.await()阻塞主線程。
每當(dāng)一個(gè)線程執(zhí)行完一個(gè)指定動(dòng)作之后,count就會(huì)減少1,當(dāng)count等于0時(shí),主線程不再阻塞,開始繼續(xù)執(zhí)行下面的代碼,當(dāng)count大于0時(shí),主線程一直阻塞,等待count變?yōu)?。每個(gè)線程動(dòng)作執(zhí)行結(jié)束后,執(zhí)行countDownLatch.countDown(),這個(gè)門栓的count減一。
int ThreadNum = 16; CountDownLatch countDownLatch = new CountDownLatch(ThreadNum); for(int i = 0; i < ThreadNum ; i++){ final int finalI = i; new Thread(() -> { int n = 0; System.out.println("線程應(yīng)該做的事情"); while(n < 10){ n++; } countDownLatch.countDown(); }).start(); } try{ countDownLatch.await(); }catch(InterruptedException e){ logger.infor("InterruptedException!!"); }
2.線程池
其實(shí)線程池之前的ipv6的項(xiàng)目里用過,但是也忘記得差不多了,復(fù)習(xí)一下。
線程在創(chuàng)建和關(guān)閉時(shí)都需要花費(fèi)時(shí)間,如果為每一個(gè)小的任務(wù)都創(chuàng)建一個(gè)線程,可能創(chuàng)建和銷毀線程所用的時(shí)間會(huì)多于該線程真實(shí)工作所消耗的時(shí)間,就會(huì)得不償失。除了時(shí)間,空間也需要考慮,線程本身也是要占用內(nèi)存空間的,大量的線程會(huì)食用過多的內(nèi)存資源,可能會(huì)造成OOM。另外在回收時(shí),大量的線程會(huì)延長(zhǎng)GC的停頓時(shí)間。
因此在生產(chǎn)環(huán)境中使用線程必須對(duì)其加以控制和管理
使用線程池之后,創(chuàng)建線程變成了從線程池中獲得空閑的線程,關(guān)閉線程變成了歸還線程給線程池。
通過ThreadPoolExecutor可以創(chuàng)建一個(gè)線程池,ThreadPoolExecutor實(shí)現(xiàn)了Executors接口。
舉個(gè)栗子:
import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.ThreadFactory; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; public class ThreadPoolTest { public static void main(String[] args) { ThreadPoolExecutor pool = new ThreadPoolExecutor(10,20,60, TimeUnit.SECOUNDS,new ArrayBlockingQueue<Runnable>(15000),new ThreadFactory(){ private AtomicInteger threadId = new AtomicInteger(0); @Override public Thread newThread(Runnable r){ Thread thread = new Thread(r); thread.setDaemon(true); String prefix = "thread-"; thread.setName(prefix+threadId.incrementAndGet()); return thread; } }); } }
這樣就創(chuàng)建了一個(gè)線程池。參數(shù)依次解釋:
corePoolSize:指定了線程池中線程的數(shù)量,線程池中可以有10個(gè)存活的線程
maximumPoolSize:指定了線程池中最大的線程數(shù),線程池中最多能有20個(gè)存活的線程
keepAliveTime:當(dāng)線程池中的數(shù)量超過corePoolSize時(shí),這些線程在多長(zhǎng)時(shí)間會(huì)被銷毀,60s
unit:keepAliveTime的單位
workQueue:任務(wù)隊(duì)列,被提交但是沒有被執(zhí)行的任務(wù)存在的地方。他是一個(gè)BlockingQueue<Runnable>接口的對(duì)象。
threadFactory:線程工廠,你想創(chuàng)建什么樣子的線程
重點(diǎn)說一下workQueue:
根據(jù)隊(duì)列的功能分類,可以使用以下幾種BlockingQueue接口
補(bǔ)充:Java中CountDownLatch,CyclicBarrier以及Semaphore的使用場(chǎng)景
Java并發(fā)包中提供了很多有用的工具類來(lái)幫助開發(fā)者進(jìn)行并發(fā)編程,今天我就來(lái)說說CountDownLatch,CyclicBarrier以及Semaphore這三個(gè)的用法和使用場(chǎng)景。
1.CountDownLatch使用場(chǎng)景和用法
CountDownLatch一般是用于某個(gè)線程等待其他線程執(zhí)行完之后,它才能執(zhí)行。例如一家人在等待爸爸媽媽回家,才能進(jìn)行晚宴,示例代碼如下:
public class CountDownLatchTest { public static void main(String[] args) throws Exception { final CountDownLatch cdl = new CountDownLatch(2); new Thread(){ public void run() { try { System.out.println("等待老爸回家..."); Thread.sleep(5000); cdl.countDown(); } catch (InterruptedException e) { e.printStackTrace(); } }; }.start(); new Thread(){ public void run() { try { System.out.println("等待老媽回家..."); Thread.sleep(5000); cdl.countDown(); } catch (InterruptedException e) { e.printStackTrace(); } }; }.start(); cdl.await(); System.out.println("老爸老媽回來(lái)了..."); System.out.println("晚宴開始了..."); } }
2.CyclicBarrier(柵欄)使用場(chǎng)景和用法
CyclicBarrier一般是一組線程等待至某個(gè)狀態(tài),然后這一組線程才能同時(shí)執(zhí)行(感覺跟CountDownLatch有點(diǎn)類似啊,不過仔細(xì)想想還是有差別的,感覺容易混淆)。
代碼示例如下:
public class CyclicBarrierTest { public static void main(String[] args) { int count = 3; CyclicBarrier cb = new CyclicBarrier(count, new Runnable() { @Override public void run() { //此處所有線程都調(diào)用了await方法之后,會(huì)走到這里 System.out.println("所有線程操作完成之后都調(diào)用了await方法"); } }); for(int i=0;i<count;i++){ new WriteLogHandler(cb).start(); } } static class WriteLogHandler extends Thread{ private CyclicBarrier cb = null; public WriteLogHandler(CyclicBarrier cb) { this.cb = cb; } @Override public void run() { try { System.out.println("線程:" + Thread.currentThread().getName() + "開始寫日志"); Thread.sleep(2000); System.out.println("線程:" + Thread.currentThread().getName() + "寫日志結(jié)束,等待其他線程"); cb.await(); System.out.println("所有線程寫日志數(shù)據(jù)結(jié)束,繼續(xù)其他操作"); } catch (Exception e) { e.printStackTrace(); } } } }
3.Semaphore(信號(hào)量)使用場(chǎng)景和用法
Semaphore類似鎖的用法,用于控制對(duì)某資源的訪問權(quán)限,示例代碼如下: public class SemaphoreTest { public static void main(String[] args) { ExecutorService executor = Executors.newCachedThreadPool(); final Semaphore semaphore = new Semaphore(5); for(int i=0;i<10;i++){ final int num = i; executor.execute(new Runnable() { @Override public void run() { try { semaphore.acquire(); System.out.println("正在執(zhí)行任務(wù)" + num); Thread.sleep((long)Math.random() * 1000); System.out.println("任務(wù)" + num + "執(zhí)行結(jié)束"); semaphore.release(); } catch (Exception e) { e.printStackTrace(); } } }); } executor.shutdown(); } }
以上就是這三個(gè)并發(fā)工具類的使用場(chǎng)景和示例,僅為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教。歡迎大家一起交流。
相關(guān)文章
Springboot整合Shiro實(shí)現(xiàn)登錄與權(quán)限校驗(yàn)詳細(xì)解讀
本文給大家介紹Springboot整合Shiro的基本使用,Apache?Shiro是Java的一個(gè)安全框架,Shiro本身無(wú)法知道所持有令牌的用戶是否合法,我們將整合Shiro實(shí)現(xiàn)登錄與權(quán)限的驗(yàn)證2022-04-04使用Mybatis-plus清空表數(shù)據(jù)的操作方法
MyBatis 是一個(gè)基于 java 的持久層框架,它內(nèi)部封裝了 jdbc,極大提高了我們的開發(fā)效率,文中給大家介紹了MybatisPlus常用API-增刪改查功能,感興趣的朋友跟隨小編一起看看吧2022-11-11MyBatis詳細(xì)執(zhí)行流程的全紀(jì)錄
這篇文章主要給大家介紹了關(guān)于MyBatis詳細(xì)執(zhí)行流程的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-04-04java實(shí)現(xiàn)web實(shí)時(shí)消息推送的七種方案
這篇文章主要為大家介紹了java實(shí)現(xiàn)web實(shí)時(shí)消息推送的七種方案示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-07-07Spring Cloud Zuul路由網(wǎng)關(guān)服務(wù)過濾實(shí)現(xiàn)代碼
這篇文章主要介紹了Spring Cloud Zuul路由網(wǎng)關(guān)服務(wù)過濾實(shí)現(xiàn)代碼,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-04-04詳解Spring Boot最新版優(yōu)雅停機(jī)的方法
這篇文章主要介紹了Spring Boot最新版優(yōu)雅停機(jī)的相關(guān)知識(shí),本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-10-10