摘要:示例執(zhí)行一批任務(wù),然后消費(fèi)執(zhí)行結(jié)果代碼如下跟著阿里學(xué)并發(fā),微信公眾號(hào)輸出代碼中傳入了一批任務(wù)進(jìn)行處理,最終將所有處理完成的按任務(wù)完成的先后順序傳遞給進(jìn)行消費(fèi)了。
這是java高并發(fā)系列第20篇文章。
本文內(nèi)容ExecutorCompletionService出現(xiàn)的背景
介紹CompletionService接口及常用的方法
介紹ExecutorCompletionService類及其原理
示例:執(zhí)行一批任務(wù),然后消費(fèi)執(zhí)行結(jié)果
示例【2種方式】:異步執(zhí)行一批任務(wù),有一個(gè)完成立即返回,其他取消
需要解決的問題還是舉個(gè)例子說明更好理解一些。
買新房了,然后在網(wǎng)上下單買冰箱、洗衣機(jī),電器商家不同,所以送貨耗時(shí)不一樣,然后等他們送貨,快遞只愿送到樓下,然后我們自己將其搬到樓上的家中。
用程序來模擬上面的實(shí)現(xiàn)。示例代碼如下:
package com.itsoku.chat18; import java.util.concurrent.*; /** * 跟著阿里p7學(xué)并發(fā),微信公眾號(hào):javacode2018 */ public class Demo12 { static class GoodsModel { //商品名稱 String name; //購物開始時(shí)間 long startime; //送到的時(shí)間 long endtime; public GoodsModel(String name, long startime, long endtime) { this.name = name; this.startime = startime; this.endtime = endtime; } @Override public String toString() { return name + ",下單時(shí)間[" + this.startime + "," + endtime + "],耗時(shí):" + (this.endtime - this.startime); } } /** * 將商品搬上樓 * * @param goodsModel * @throws InterruptedException */ static void moveUp(GoodsModel goodsModel) throws InterruptedException { //休眠5秒,模擬搬上樓耗時(shí) TimeUnit.SECONDS.sleep(5); System.out.println("將商品搬上樓,商品信息:" + goodsModel); } /** * 模擬下單 * * @param name 商品名稱 * @param costTime 耗時(shí) * @return */ static CallablebuyGoods(String name, long costTime) { return () -> { long startTime = System.currentTimeMillis(); System.out.println(startTime + "購買" + name + "下單!"); //模擬送貨耗時(shí) try { TimeUnit.SECONDS.sleep(costTime); } catch (InterruptedException e) { e.printStackTrace(); } long endTime = System.currentTimeMillis(); System.out.println(startTime + name + "送到了!"); return new GoodsModel(name, startTime, endTime); }; } public static void main(String[] args) throws InterruptedException, ExecutionException { long st = System.currentTimeMillis(); System.out.println(st + "開始購物!"); //創(chuàng)建一個(gè)線程池,用來異步下單 ExecutorService executor = Executors.newFixedThreadPool(5); //異步下單購買冰箱 Future bxFuture = executor.submit(buyGoods("冰箱", 5)); //異步下單購買洗衣機(jī) Future xyjFuture = executor.submit(buyGoods("洗衣機(jī)", 2)); //關(guān)閉線程池 executor.shutdown(); //等待冰箱送到 GoodsModel bxGoodModel = bxFuture.get(); //將冰箱搬上樓 moveUp(bxGoodModel); //等待洗衣機(jī)送到 GoodsModel xyjGooldModel = xyjFuture.get(); //將洗衣機(jī)搬上樓 moveUp(xyjGooldModel); long et = System.currentTimeMillis(); System.out.println(et + "貨物已送到家里咯,哈哈哈!"); System.out.println("總耗時(shí):" + (et - st)); } }
輸出:
1564653121515開始購物! 1564653121588購買冰箱下單! 1564653121588購買洗衣機(jī)下單! 1564653121588洗衣機(jī)送到了! 1564653121588冰箱送到了! 將商品搬上樓,商品信息:冰箱,下單時(shí)間[1564653121588,1564653126590],耗時(shí):5002 將商品搬上樓,商品信息:洗衣機(jī),下單時(shí)間[1564653121588,1564653123590],耗時(shí):2002 1564653136591貨物已送到家里咯,哈哈哈! 總耗時(shí):15076
從輸出中我們可以看出幾個(gè)時(shí)間:
購買冰箱耗時(shí)5秒
購買洗衣機(jī)耗時(shí)2秒
將冰箱送上樓耗時(shí)5秒
將洗衣機(jī)送上樓耗時(shí)5秒
共計(jì)耗時(shí)15秒
購買洗衣機(jī)、冰箱都是異步執(zhí)行的,我們先把冰箱送上樓了,然后再把冰箱送上樓了。上面大家應(yīng)該發(fā)現(xiàn)了一個(gè)問題,洗衣機(jī)先到的,洗衣機(jī)到了,我們并沒有去把洗衣機(jī)送上樓,而是在等待冰箱到貨(bxFuture.get();),然后將冰箱送上樓,中間導(dǎo)致浪費(fèi)了3秒,現(xiàn)實(shí)中應(yīng)該是這樣的,先到的先送上樓,修改一下代碼,洗衣機(jī)先到的,先送洗衣機(jī)上樓,代碼如下:
package com.itsoku.chat18; import java.util.concurrent.*; /** * 跟著阿里p7學(xué)并發(fā),微信公眾號(hào):javacode2018 */ public class Demo13 { static class GoodsModel { //商品名稱 String name; //購物開始時(shí)間 long startime; //送到的時(shí)間 long endtime; public GoodsModel(String name, long startime, long endtime) { this.name = name; this.startime = startime; this.endtime = endtime; } @Override public String toString() { return name + ",下單時(shí)間[" + this.startime + "," + endtime + "],耗時(shí):" + (this.endtime - this.startime); } } /** * 將商品搬上樓 * * @param goodsModel * @throws InterruptedException */ static void moveUp(GoodsModel goodsModel) throws InterruptedException { //休眠5秒,模擬搬上樓耗時(shí) TimeUnit.SECONDS.sleep(5); System.out.println("將商品搬上樓,商品信息:" + goodsModel); } /** * 模擬下單 * * @param name 商品名稱 * @param costTime 耗時(shí) * @return */ static CallablebuyGoods(String name, long costTime) { return () -> { long startTime = System.currentTimeMillis(); System.out.println(startTime + "購買" + name + "下單!"); //模擬送貨耗時(shí) try { TimeUnit.SECONDS.sleep(costTime); } catch (InterruptedException e) { e.printStackTrace(); } long endTime = System.currentTimeMillis(); System.out.println(endTime + name + "送到了!"); return new GoodsModel(name, startTime, endTime); }; } public static void main(String[] args) throws InterruptedException, ExecutionException { long st = System.currentTimeMillis(); System.out.println(st + "開始購物!"); //創(chuàng)建一個(gè)線程池,用來異步下單 ExecutorService executor = Executors.newFixedThreadPool(5); //異步下單購買冰箱 Future bxFuture = executor.submit(buyGoods("冰箱", 5)); //異步下單購買洗衣機(jī) Future xyjFuture = executor.submit(buyGoods("洗衣機(jī)", 2)); //關(guān)閉線程池 executor.shutdown(); //等待洗衣機(jī)送到 GoodsModel xyjGooldModel = xyjFuture.get(); //將洗衣機(jī)搬上樓 moveUp(xyjGooldModel); //等待冰箱送到 GoodsModel bxGoodModel = bxFuture.get(); //將冰箱搬上樓 moveUp(bxGoodModel); long et = System.currentTimeMillis(); System.out.println(et + "貨物已送到家里咯,哈哈哈!"); System.out.println("總耗時(shí):" + (et - st)); } }
輸出:
1564653153393開始購物! 1564653153466購買洗衣機(jī)下單! 1564653153466購買冰箱下單! 1564653155467洗衣機(jī)送到了! 1564653158467冰箱送到了! 將商品搬上樓,商品信息:洗衣機(jī),下單時(shí)間[1564653153466,1564653155467],耗時(shí):2001 將商品搬上樓,商品信息:冰箱,下單時(shí)間[1564653153466,1564653158467],耗時(shí):5001 1564653165469貨物已送到家里咯,哈哈哈! 總耗時(shí):12076
耗時(shí)12秒,比第一種少了3秒。
問題來了,上面是我們通過調(diào)整代碼達(dá)到了最優(yōu)效果,實(shí)際上,購買冰箱和洗衣機(jī)具體哪個(gè)耗時(shí)時(shí)間長我們是不知道的,怎么辦呢,有沒有什么解決辦法?
CompletionService接口CompletionService相當(dāng)于一個(gè)執(zhí)行任務(wù)的服務(wù),通過submit丟任務(wù)給這個(gè)服務(wù),服務(wù)內(nèi)部去執(zhí)行任務(wù),可以通過服務(wù)提供的一些方法獲取服務(wù)中已經(jīng)完成的任務(wù)。
接口內(nèi)的幾個(gè)方法:
Futuresubmit(Callable task);
用于向服務(wù)中提交有返回結(jié)果的任務(wù),并返回Future對象
Futuresubmit(Runnable task, V result);
用戶向服務(wù)中提交有返回值的任務(wù)去執(zhí)行,并返回Future對象
Futuretake() throws InterruptedException;
從服務(wù)中返回并移除一個(gè)已經(jīng)完成的任務(wù),如果獲取不到,會(huì)一致阻塞到有返回值為止。此方法會(huì)響應(yīng)線程中斷。
Futurepoll();
從服務(wù)中返回并移除一個(gè)已經(jīng)完成的任務(wù),如果內(nèi)部沒有已經(jīng)完成的任務(wù),則返回空,此方法會(huì)立即響應(yīng)。
Futurepoll(long timeout, TimeUnit unit) throws InterruptedException;
嘗試在指定的時(shí)間內(nèi)從服務(wù)中返回并移除一個(gè)已經(jīng)完成的任務(wù),等待的時(shí)間超時(shí)還是沒有獲取到已完成的任務(wù),則返回空。此方法會(huì)響應(yīng)線程中斷
通過submit向內(nèi)部提交任意多個(gè)任務(wù),通過take方法可以獲取已經(jīng)執(zhí)行完成的任務(wù),如果獲取不到將等待。
ExecutorCompletionService類ExecutorCompletionService類是CompletionService接口的具體實(shí)現(xiàn)。
說一下其內(nèi)部原理,ExecutorCompletionService創(chuàng)建的時(shí)候會(huì)傳入一個(gè)線程池,調(diào)用submit方法傳入需要執(zhí)行的任務(wù),任務(wù)由內(nèi)部的線程池來處理;ExecutorCompletionService內(nèi)部有個(gè)阻塞隊(duì)列,任意一個(gè)任務(wù)完成之后,會(huì)將任務(wù)的執(zhí)行結(jié)果(Future類型)放入阻塞隊(duì)列中,然后其他線程可以調(diào)用它take、poll方法從這個(gè)阻塞隊(duì)列中獲取一個(gè)已經(jīng)完成的任務(wù),獲取任務(wù)返回結(jié)果的順序和任務(wù)執(zhí)行完成的先后順序一致,所以最先完成的任務(wù)會(huì)先返回。
關(guān)于阻塞隊(duì)列的知識(shí)后面會(huì)專門抽幾篇來講,大家可以關(guān)注一下后面的文章。
看一下構(gòu)造方法:
public ExecutorCompletionService(Executor executor) { if (executor == null) throw new NullPointerException(); this.executor = executor; this.aes = (executor instanceof AbstractExecutorService) ? (AbstractExecutorService) executor : null; this.completionQueue = new LinkedBlockingQueue>(); }
構(gòu)造方法需要傳入一個(gè)Executor對象,這個(gè)對象表示任務(wù)執(zhí)行器,所有傳入的任務(wù)會(huì)被這個(gè)執(zhí)行器執(zhí)行。
completionQueue是用來存儲(chǔ)任務(wù)結(jié)果的阻塞隊(duì)列,默認(rèn)用采用的是LinkedBlockingQueue,也支持開發(fā)自己設(shè)置。通過submit傳入需要執(zhí)行的任務(wù),任務(wù)執(zhí)行完成之后,會(huì)放入completionQueue中,有興趣的可以看一下原碼,還是很好理解的。
使用ExecutorCompletionService解決文章開頭的問題代碼如下:
package com.itsoku.chat18; import java.util.concurrent.*; /** * 跟著阿里p7學(xué)并發(fā),微信公眾號(hào):javacode2018 */ public class Demo14 { static class GoodsModel { //商品名稱 String name; //購物開始時(shí)間 long startime; //送到的時(shí)間 long endtime; public GoodsModel(String name, long startime, long endtime) { this.name = name; this.startime = startime; this.endtime = endtime; } @Override public String toString() { return name + ",下單時(shí)間[" + this.startime + "," + endtime + "],耗時(shí):" + (this.endtime - this.startime); } } /** * 將商品搬上樓 * * @param goodsModel * @throws InterruptedException */ static void moveUp(GoodsModel goodsModel) throws InterruptedException { //休眠5秒,模擬搬上樓耗時(shí) TimeUnit.SECONDS.sleep(5); System.out.println("將商品搬上樓,商品信息:" + goodsModel); } /** * 模擬下單 * * @param name 商品名稱 * @param costTime 耗時(shí) * @return */ static CallablebuyGoods(String name, long costTime) { return () -> { long startTime = System.currentTimeMillis(); System.out.println(startTime + "購買" + name + "下單!"); //模擬送貨耗時(shí) try { TimeUnit.SECONDS.sleep(costTime); } catch (InterruptedException e) { e.printStackTrace(); } long endTime = System.currentTimeMillis(); System.out.println(endTime + name + "送到了!"); return new GoodsModel(name, startTime, endTime); }; } public static void main(String[] args) throws InterruptedException, ExecutionException { long st = System.currentTimeMillis(); System.out.println(st + "開始購物!"); ExecutorService executor = Executors.newFixedThreadPool(5); //創(chuàng)建ExecutorCompletionService對象 ExecutorCompletionService executorCompletionService = new ExecutorCompletionService<>(executor); //異步下單購買冰箱 executorCompletionService.submit(buyGoods("冰箱", 5)); //異步下單購買洗衣機(jī) executorCompletionService.submit(buyGoods("洗衣機(jī)", 2)); executor.shutdown(); //購買商品的數(shù)量 int goodsCount = 2; for (int i = 0; i < goodsCount; i++) { //可以獲取到最先到的商品 GoodsModel goodsModel = executorCompletionService.take().get(); //將最先到的商品送上樓 moveUp(goodsModel); } long et = System.currentTimeMillis(); System.out.println(et + "貨物已送到家里咯,哈哈哈!"); System.out.println("總耗時(shí):" + (et - st)); } }
輸出:
1564653208284開始購物! 1564653208349購買冰箱下單! 1564653208349購買洗衣機(jī)下單! 1564653210349洗衣機(jī)送到了! 1564653213350冰箱送到了! 將商品搬上樓,商品信息:洗衣機(jī),下單時(shí)間[1564653208349,1564653210349],耗時(shí):2000 將商品搬上樓,商品信息:冰箱,下單時(shí)間[1564653208349,1564653213350],耗時(shí):5001 1564653220350貨物已送到家里咯,哈哈哈! 總耗時(shí):12066
從輸出中可以看出和我們希望的結(jié)果一致,代碼中下單順序是:冰箱、洗衣機(jī),冰箱送貨耗時(shí)5秒,洗衣機(jī)送貨耗時(shí)2秒,洗衣機(jī)先到的,然后被送上樓了,冰箱后到被送上樓,總共耗時(shí)12秒,和期望的方案一樣。
示例:執(zhí)行一批任務(wù),然后消費(fèi)執(zhí)行結(jié)果代碼如下:
package com.itsoku.chat18; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.concurrent.*; import java.util.function.Consumer; /** * 跟著阿里p7學(xué)并發(fā),微信公眾號(hào):javacode2018 */ public class Demo15 { public static void main(String[] args) throws ExecutionException, InterruptedException { ExecutorService executorService = Executors.newFixedThreadPool(5); List> list = new ArrayList<>(); int taskCount = 5; for (int i = taskCount; i > 0; i--) { int j = i * 2; list.add(() -> { TimeUnit.SECONDS.sleep(j); return j; }); } solve(executorService, list, a -> { System.out.println(System.currentTimeMillis() + ":" + a); }); executorService.shutdown(); } public static void solve(Executor e, Collection > solvers, Consumer use) throws InterruptedException, ExecutionException { CompletionService ecs = new ExecutorCompletionService (e); for (Callable s : solvers) { ecs.submit(s); } int n = solvers.size(); for (int i = 0; i < n; ++i) { T r = ecs.take().get(); if (r != null) { use.accept(r); } } } }
輸出:
1564667625648:2 1564667627652:4 1564667629649:6 1564667631652:8 1564667633651:10
代碼中傳入了一批任務(wù)進(jìn)行處理,最終將所有處理完成的按任務(wù)完成的先后順序傳遞給Consumer進(jìn)行消費(fèi)了。
示例:異步執(zhí)行一批任務(wù),有一個(gè)完成立即返回,其他取消這個(gè)給大家講解2種方式。
方式1使用ExecutorCompletionService實(shí)現(xiàn),ExecutorCompletionService提供了獲取一批任務(wù)中最先完成的任務(wù)結(jié)果的能力。
代碼如下:
package com.itsoku.chat18; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.concurrent.*; import java.util.function.Consumer; /** * 跟著阿里p7學(xué)并發(fā),微信公眾號(hào):javacode2018 */ public class Demo16 { public static void main(String[] args) throws ExecutionException, InterruptedException { long startime = System.currentTimeMillis(); ExecutorService executorService = Executors.newFixedThreadPool(5); List> list = new ArrayList<>(); int taskCount = 5; for (int i = taskCount; i > 0; i--) { int j = i * 2; String taskName = "任務(wù)"+i; list.add(() -> { TimeUnit.SECONDS.sleep(j); System.out.println(taskName+"執(zhí)行完畢!"); return j; }); } Integer integer = invokeAny(executorService, list); System.out.println("耗時(shí):" + (System.currentTimeMillis() - startime) + ",執(zhí)行結(jié)果:" + integer); executorService.shutdown(); } public static T invokeAny(Executor e, Collection > solvers) throws InterruptedException, ExecutionException { CompletionService ecs = new ExecutorCompletionService (e); List > futureList = new ArrayList<>(); for (Callable s : solvers) { futureList.add(ecs.submit(s)); } int n = solvers.size(); try { for (int i = 0; i < n; ++i) { T r = ecs.take().get(); if (r != null) { return r; } } } finally { for (Future future : futureList) { future.cancel(true); } } return null; } }
程序輸出下面結(jié)果然后停止了:
任務(wù)1執(zhí)行完畢! 耗時(shí):2072,執(zhí)行結(jié)果:2
代碼中執(zhí)行了5個(gè)任務(wù),使用CompletionService執(zhí)行任務(wù),調(diào)用take方法獲取最先執(zhí)行完成的任務(wù),然后返回。在finally中對所有任務(wù)發(fā)送取消操作(future.cancel(true);),從輸出中可以看出只有任務(wù)1執(zhí)行成功,其他任務(wù)被成功取消了,符合預(yù)期結(jié)果。
方式2其實(shí)ExecutorService已經(jīng)為我們提供了這樣的方法,方法聲明如下:
T invokeAny(Collection extends Callable > tasks) throws InterruptedException, ExecutionException;
示例代碼:
package com.itsoku.chat18; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.concurrent.*; /** * 跟著阿里p7學(xué)并發(fā),微信公眾號(hào):javacode2018 */ public class Demo17 { public static void main(String[] args) throws ExecutionException, InterruptedException { long startime = System.currentTimeMillis(); ExecutorService executorService = Executors.newFixedThreadPool(5); List> list = new ArrayList<>(); int taskCount = 5; for (int i = taskCount; i > 0; i--) { int j = i * 2; String taskName = "任務(wù)" + i; list.add(() -> { TimeUnit.SECONDS.sleep(j); System.out.println(taskName + "執(zhí)行完畢!"); return j; }); } Integer integer = executorService.invokeAny(list); System.out.println("耗時(shí):" + (System.currentTimeMillis() - startime) + ",執(zhí)行結(jié)果:" + integer); executorService.shutdown(); } }
輸出下面結(jié)果之后停止:
任務(wù)1執(zhí)行完畢! 耗時(shí):2061,執(zhí)行結(jié)果:2
輸出結(jié)果和方式1中結(jié)果類似。
java高并發(fā)系列java高并發(fā)系列 - 第1天:必須知道的幾個(gè)概念
java高并發(fā)系列 - 第2天:并發(fā)級(jí)別
java高并發(fā)系列 - 第3天:有關(guān)并行的兩個(gè)重要定律
java高并發(fā)系列 - 第4天:JMM相關(guān)的一些概念
java高并發(fā)系列 - 第5天:深入理解進(jìn)程和線程
java高并發(fā)系列 - 第6天:線程的基本操作
java高并發(fā)系列 - 第7天:volatile與Java內(nèi)存模型
java高并發(fā)系列 - 第8天:線程組
java高并發(fā)系列 - 第9天:用戶線程和守護(hù)線程
java高并發(fā)系列 - 第10天:線程安全和synchronized關(guān)鍵字
java高并發(fā)系列 - 第11天:線程中斷的幾種方式
java高并發(fā)系列 - 第12天JUC:ReentrantLock重入鎖
java高并發(fā)系列 - 第13天:JUC中的Condition對象
java高并發(fā)系列 - 第14天:JUC中的LockSupport工具類,必備技能
java高并發(fā)系列 - 第15天:JUC中的Semaphore(信號(hào)量)
java高并發(fā)系列 - 第16天:JUC中等待多線程完成的工具類CountDownLatch,必備技能
java高并發(fā)系列 - 第17天:JUC中的循環(huán)柵欄CyclicBarrier的6種使用場景
java高并發(fā)系列 - 第18天:JAVA線程池,這一篇就夠了
java高并發(fā)系列 - 第19天:JUC中的Executor框架詳解1
阿里p7一起學(xué)并發(fā),公眾號(hào):路人甲java,每天獲取最新文章!
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/75756.html
摘要:有三種狀態(tài)運(yùn)行關(guān)閉終止。類類,提供了一系列工廠方法用于創(chuàng)建線程池,返回的線程池都實(shí)現(xiàn)了接口。線程池的大小一旦達(dá)到最大值就會(huì)保持不變,在提交新任務(wù),任務(wù)將會(huì)進(jìn)入等待隊(duì)列中等待。此線程池支持定時(shí)以及周期性執(zhí)行任務(wù)的需求。 這是java高并發(fā)系列第19篇文章。 本文主要內(nèi)容 介紹Executor框架相關(guān)內(nèi)容 介紹Executor 介紹ExecutorService 介紹線程池ThreadP...
摘要:方法由兩個(gè)參數(shù),表示期望的值,表示要給設(shè)置的新值。操作包含三個(gè)操作數(shù)內(nèi)存位置預(yù)期原值和新值。如果處的值尚未同時(shí)更改,則操作成功。中就使用了這樣的操作。上面操作還有一點(diǎn)是將事務(wù)范圍縮小了,也提升了系統(tǒng)并發(fā)處理的性能。 這是java高并發(fā)系列第21篇文章。 本文主要內(nèi)容 從網(wǎng)站計(jì)數(shù)器實(shí)現(xiàn)中一步步引出CAS操作 介紹java中的CAS及CAS可能存在的問題 悲觀鎖和樂觀鎖的一些介紹及數(shù)據(jù)庫...
摘要:如問到是否使用某框架,實(shí)際是是問該框架的使用場景,有什么特點(diǎn),和同類可框架對比一系列的問題。這兩個(gè)方向的區(qū)分點(diǎn)在于工作方向的側(cè)重點(diǎn)不同。 [TOC] 這是一份來自嗶哩嗶哩的Java面試Java面試 32個(gè)核心必考點(diǎn)完全解析(完) 課程預(yù)習(xí) 1.1 課程內(nèi)容分為三個(gè)模塊 基礎(chǔ)模塊: 技術(shù)崗位與面試 計(jì)算機(jī)基礎(chǔ) JVM原理 多線程 設(shè)計(jì)模式 數(shù)據(jù)結(jié)構(gòu)與算法 應(yīng)用模塊: 常用工具集 ...
摘要:整個(gè)包,按照功能可以大致劃分如下鎖框架原子類框架同步器框架集合框架執(zhí)行器框架本系列將按上述順序分析,分析所基于的源碼為。后,根據(jù)一系列常見的多線程設(shè)計(jì)模式,設(shè)計(jì)了并發(fā)包,其中包下提供了一系列基礎(chǔ)的鎖工具,用以對等進(jìn)行補(bǔ)充增強(qiáng)。 showImg(https://segmentfault.com/img/remote/1460000016012623); 本文首發(fā)于一世流云專欄:https...
摘要:高并發(fā)系列第篇文章。簡單的說,在使用了線程池之后,創(chuàng)建線程變成了從線程池中獲取一個(gè)空閑的線程,然后使用,關(guān)閉線程變成了將線程歸還到線程池。如果調(diào)用了線程池的方法,線程池會(huì)提前把核心線程都創(chuàng)造好,并啟動(dòng)線程池允許創(chuàng)建的最大線程數(shù)。 java高并發(fā)系列第18篇文章。 本文主要內(nèi)容 什么是線程池 線程池實(shí)現(xiàn)原理 線程池中常見的各種隊(duì)列 自定義線程創(chuàng)建的工廠 常見的飽和策略 自定義飽和策略 ...
閱讀 1115·2021-09-22 15:37
閱讀 1141·2021-09-13 10:27
閱讀 2486·2021-08-25 09:38
閱讀 2457·2019-08-26 11:42
閱讀 1538·2019-08-26 11:39
閱讀 1569·2019-08-26 10:58
閱讀 2332·2019-08-26 10:56
閱讀 2580·2019-08-23 18:08