摘要:本人郵箱歡迎轉(zhuǎn)載轉(zhuǎn)載請(qǐng)注明網(wǎng)址代碼已經(jīng)全部托管有需要的同學(xué)自行下載引言講完了和今天講一個(gè)跟這兩個(gè)類有點(diǎn)類似的移相器中引入了一種新的可重復(fù)使用的同步屏障稱為移相器擁有與和類似的功勞但是這個(gè)類提供了更加靈活的應(yīng)用和都是只適用于固定數(shù)量的參與者
引言本人郵箱:
歡迎轉(zhuǎn)載,轉(zhuǎn)載請(qǐng)注明網(wǎng)址 http://blog.csdn.net/tianshi_kco
github: https://github.com/kco1989/kco
代碼已經(jīng)全部托管github有需要的同學(xué)自行下載
講完了CyclicBarrier和CountDownLatch,今天講一個(gè)跟這兩個(gè)類有點(diǎn)類似的Phaser.->移相器
例子1 用Phaser代替CyclicBarrierjava7中引入了一種新的可重復(fù)使用的同步屏障,稱為移相器Phaser.Phaser擁有與CyclicBarrier和CountDownLatch類似的功勞.但是這個(gè)類提供了更加靈活的應(yīng)用.CountDownLatch和CyclicBarrier都是只適用于固定數(shù)量的參與者.移相器適用于可變數(shù)目的屏障,在這個(gè)意義上,可以在任何時(shí)間注冊(cè)新的參與者.并且在抵達(dá)屏障是可以注銷已經(jīng)注冊(cè)的參與者.因此,注冊(cè)到同步移相器的參與者的數(shù)目可能會(huì)隨著時(shí)間的推移而變化.如CyclicBarrier一樣,移相器可以重復(fù)使用,這意味著當(dāng)前參與者到達(dá)移相器后,可以再一次注冊(cè)自己并等待另一次到達(dá).因此,移相器會(huì)有多代.一旦為某個(gè)特定相位注冊(cè)的所有參與者都到達(dá)移相器,就增加相數(shù).相數(shù)從零開始,在達(dá)到Integer.MAX_VALUE后,再次繞回0.當(dāng)移相器發(fā)生變化時(shí),通過重寫onAdvance方法,可以自行可選操作.這個(gè)方法也可用于終止移相器.移相器一旦被終止,所有的同步方法就會(huì)立即返回,并嘗試注冊(cè)新的失敗的參與者.
移相器的另一個(gè)重要特征是:移相器可能是分層的,這允許你以樹形結(jié)構(gòu)來安排移相器以減少競(jìng)爭(zhēng).很明顯,更小的組將擁有更少的競(jìng)爭(zhēng)同步的參與者.因此,將大量的參與者分成較小的組可以減少競(jìng)爭(zhēng).雖然創(chuàng)建移相器能增加中的吞吐量,但是這需要更多的開銷.最后,移相器的另一個(gè)重要的特征在于監(jiān)控功能,使用獨(dú)立的對(duì)象可以監(jiān)視移相器的當(dāng)前狀態(tài).監(jiān)視器可以查詢注冊(cè)到移相器的參與者的數(shù)量,以及已經(jīng)到達(dá)和還沒有到達(dá)某個(gè)特定相數(shù)的參與者的數(shù)量.1
將之前(九)java多線程之CyclicBarrier旅游的例子改寫一下,
Phaser替代CyclicBarrier比較簡(jiǎn)單,CyclicBarrier的await()方法可以直接用Phaser的arriveAndAwaitAdvance()方法替代
CyclicBarrier與Phaser:CyclicBarrier只適用于固定數(shù)量的參與者,而Phaser適用于可變數(shù)目的屏障.
TourismRunnable 旅游類
public class TourismRunnable implements Runnable{ Phaser phaser; Random random; public TourismRunnable(Phaser phaser) { this.phaser = phaser; this.random = new Random(); } @Override public void run() { tourism(); } /** * 旅游過程 */ private void tourism() { goToStartingPoint(); goToHotel(); goToTourismPoint1(); goToTourismPoint2(); goToTourismPoint3(); goToEndPoint(); } /** * 裝備返程 */ private void goToEndPoint() { goToPoint("飛機(jī)場(chǎng),準(zhǔn)備登機(jī)回家"); } /** * 到達(dá)旅游點(diǎn)3 */ private void goToTourismPoint3() { goToPoint("旅游點(diǎn)3"); } /** * 到達(dá)旅游點(diǎn)2 */ private void goToTourismPoint2() { goToPoint("旅游點(diǎn)2"); } /** * 到達(dá)旅游點(diǎn)1 */ private void goToTourismPoint1() { goToPoint("旅游點(diǎn)1"); } /** * 入住酒店 */ private void goToHotel() { goToPoint("酒店"); } /** * 出發(fā)點(diǎn)集合 */ private void goToStartingPoint() { goToPoint("出發(fā)點(diǎn)"); } private int getRandomTime(){ int time = this.random.nextInt(400) + 100; try { Thread.sleep(time); } catch (InterruptedException e) { e.printStackTrace(); } return time; } private void goToPoint(String point){ try { String name = Thread.currentThread().getName(); System.out.println(name + " 花了 " + getRandomTime() + " 時(shí)間才到了" + point); phaser.arriveAndAwaitAdvance(); } catch (Exception e) { e.printStackTrace(); } } }
TestMain 測(cè)試類
public class TestMain { public static void main(String[] args) { String name = "明剛紅麗黑白"; Phaser phaser = new Phaser(name.length()); ListtourismThread = new ArrayList<>(); for (char ch : name.toCharArray()){ tourismThread.add(new Thread(new TourismRunnable(phaser), "小" + ch)); } for (Thread thread : tourismThread){ thread.start(); } } }
運(yùn)行結(jié)果
小紅 花了 122 時(shí)間才到了出發(fā)點(diǎn) 小明 花了 259 時(shí)間才到了出發(fā)點(diǎn) 小白 花了 267 時(shí)間才到了出發(fā)點(diǎn) 小麗 花了 306 時(shí)間才到了出發(fā)點(diǎn) 小剛 花了 385 時(shí)間才到了出發(fā)點(diǎn) 小黑 花了 486 時(shí)間才到了出發(fā)點(diǎn) 小白 花了 299 時(shí)間才到了酒店 小剛 花了 345 時(shí)間才到了酒店 小黑 花了 449 時(shí)間才到了酒店 小麗 花了 452 時(shí)間才到了酒店 小明 花了 462 時(shí)間才到了酒店 小紅 花了 480 時(shí)間才到了酒店 小麗 花了 107 時(shí)間才到了旅游點(diǎn)1 小紅 花了 141 時(shí)間才到了旅游點(diǎn)1 小明 花了 212 時(shí)間才到了旅游點(diǎn)1 小黑 花了 286 時(shí)間才到了旅游點(diǎn)1 小白 花了 305 時(shí)間才到了旅游點(diǎn)1 小剛 花了 386 時(shí)間才到了旅游點(diǎn)1 小麗 花了 119 時(shí)間才到了旅游點(diǎn)2 小黑 花了 222 時(shí)間才到了旅游點(diǎn)2 小明 花了 259 時(shí)間才到了旅游點(diǎn)2 小剛 花了 299 時(shí)間才到了旅游點(diǎn)2 小紅 花了 354 時(shí)間才到了旅游點(diǎn)2 小白 花了 422 時(shí)間才到了旅游點(diǎn)2 小麗 花了 112 時(shí)間才到了旅游點(diǎn)3 小白 花了 182 時(shí)間才到了旅游點(diǎn)3 小剛 花了 283 時(shí)間才到了旅游點(diǎn)3 小明 花了 295 時(shí)間才到了旅游點(diǎn)3 小紅 花了 386 時(shí)間才到了旅游點(diǎn)3 小黑 花了 483 時(shí)間才到了旅游點(diǎn)3 小黑 花了 152 時(shí)間才到了飛機(jī)場(chǎng),準(zhǔn)備登機(jī)回家 小白 花了 178 時(shí)間才到了飛機(jī)場(chǎng),準(zhǔn)備登機(jī)回家 小明 花了 248 時(shí)間才到了飛機(jī)場(chǎng),準(zhǔn)備登機(jī)回家 小紅 花了 362 時(shí)間才到了飛機(jī)場(chǎng),準(zhǔn)備登機(jī)回家 小麗 花了 428 時(shí)間才到了飛機(jī)場(chǎng),準(zhǔn)備登機(jī)回家 小剛 花了 432 時(shí)間才到了飛機(jī)場(chǎng),準(zhǔn)備登機(jī)回家
例子2 用Phaser代替CountDownLatchPhaser(int parties) 創(chuàng)建一個(gè)指定parties個(gè)線程參與同步任務(wù).
``
將之前(十)java多線程之CountDownLatch旅游回來坐飛機(jī)的例子改寫一下,
CountDownLatch主要使用的有2個(gè)方法
await()方法,可以使線程進(jìn)入等待狀態(tài),在Phaser中,與之對(duì)應(yīng)的方法是awaitAdvance(int n)。
countDown(),使計(jì)數(shù)器減一,當(dāng)計(jì)數(shù)器為0時(shí)所有等待的線程開始執(zhí)行,在Phaser中,與之對(duì)應(yīng)的方法是arrive()
Airplane飛機(jī)類
public class Airplane { private Phaser phaser; private Random random; public Airplane(int peopleNum){ phaser = new Phaser(peopleNum); random = new Random(); } /** * 下機(jī) */ public void getOffPlane(){ try { String name = Thread.currentThread().getName(); Thread.sleep(random.nextInt(500)); System.out.println(name + " 在飛機(jī)在休息著...."); Thread.sleep(random.nextInt(500)); System.out.println(name + " 下飛機(jī)了"); phaser.arrive(); } catch (InterruptedException e) { e.printStackTrace(); } } public void doWork(){ String name = Thread.currentThread().getName(); System.out.println(name + "準(zhǔn)備做 清理 工作"); phaser.awaitAdvance(phaser.getPhase()); System.out.println("飛機(jī)的乘客都下機(jī)," + name + "可以開始做 清理 工作"); } }
TestMain 測(cè)試類(沒有改)
public class TestMain { public static void main(String[] args) { String visitor = "明剛紅麗黑白"; String kongjie = "美惠花"; Airplane airplane = new Airplane(visitor.length()); Setthreads = new HashSet<>(); for (int i = 0; i < visitor.length(); i ++){ threads.add(new Thread(() -> { airplane.getOffPlane(); }, "小" + visitor.charAt(i))); } for (int i = 0; i < kongjie.length(); i ++){ threads.add(new Thread(() ->{ airplane.doWork(); }, "小" + kongjie.charAt(i) + "空姐")); } for (Thread thread : threads){ thread.start(); } } }
運(yùn)行結(jié)果
小花空姐準(zhǔn)備做 清理 工作 小惠空姐準(zhǔn)備做 清理 工作 小美空姐準(zhǔn)備做 清理 工作 小黑 在飛機(jī)在休息著.... 小明 在飛機(jī)在休息著.... 小紅 在飛機(jī)在休息著.... 小麗 在飛機(jī)在休息著.... 小剛 在飛機(jī)在休息著.... 小明 下飛機(jī)了 小紅 下飛機(jī)了 小黑 下飛機(jī)了 小白 在飛機(jī)在休息著.... 小麗 下飛機(jī)了 小剛 下飛機(jī)了 小白 下飛機(jī)了 飛機(jī)的乘客都下機(jī),小美空姐可以開始做 清理 工作 飛機(jī)的乘客都下機(jī),小花空姐可以開始做 清理 工作 飛機(jī)的乘客都下機(jī),小惠空姐可以開始做 清理 工作例子3 高級(jí)用法
前面兩個(gè)例子都比較簡(jiǎn)單,現(xiàn)在我們還用Phaser一個(gè)比較高級(jí)一點(diǎn)用法.還是用旅游的例子
假如有這么一個(gè)場(chǎng)景,在旅游過程中,有可能很湊巧遇到幾個(gè)朋友,然后他們聽說你們?cè)诼糜?所以想要加入一起繼續(xù)接下來的旅游.也有可能,在旅游過程中,突然其中有某幾個(gè)人臨時(shí)有事,想退出這次旅游了.在自由行的旅游,這是很常見的一些事情.如果現(xiàn)在我們使用CyclicBarrier這個(gè)類來實(shí)現(xiàn),我們發(fā)現(xiàn)是實(shí)現(xiàn)不了,這是用Phaser就可實(shí)現(xiàn)這個(gè)功能.
首先,我們改寫旅游類 TourismRunnable,這次改動(dòng)相對(duì)比較多一點(diǎn)
public class TourismRunnable implements Runnable{ Phaser phaser; Random random; /** * 每個(gè)線程保存一個(gè)朋友計(jì)數(shù)器,比如小紅第一次遇到一個(gè)朋友,則取名`小紅的朋友0號(hào)`, * 然后旅游到其他景點(diǎn)的時(shí)候,如果小紅又遇到一個(gè)朋友,這取名為`小紅的朋友1號(hào)` */ AtomicInteger frientCount = new AtomicInteger(); public TourismRunnable(Phaser phaser) { this.phaser = phaser; this.random = new Random(); } @Override public void run() { tourism(); } /** * 旅游過程 */ private void tourism() { switch (phaser.getPhase()){ case 0:if(!goToStartingPoint()) break; case 1:if(!goToHotel()) break; case 2:if(!goToTourismPoint1()) break; case 3:if(!goToTourismPoint2()) break; case 4:if(!goToTourismPoint3()) break; case 5:if(!goToEndPoint()) break; } } /** * 準(zhǔn)備返程 * @return 返回true,說明還要繼續(xù)旅游,否則就臨時(shí)退出了 */ private boolean goToEndPoint() { return goToPoint("飛機(jī)場(chǎng),準(zhǔn)備登機(jī)回家"); } /** * 到達(dá)旅游點(diǎn)3 * @return 返回true,說明還要繼續(xù)旅游,否則就臨時(shí)退出了 */ private boolean goToTourismPoint3() { return goToPoint("旅游點(diǎn)3"); } /** * 到達(dá)旅游點(diǎn)2 * @return 返回true,說明還要繼續(xù)旅游,否則就臨時(shí)退出了 */ private boolean goToTourismPoint2() { return goToPoint("旅游點(diǎn)2"); } /** * 到達(dá)旅游點(diǎn)1 * @return 返回true,說明還要繼續(xù)旅游,否則就臨時(shí)退出了 */ private boolean goToTourismPoint1() { return goToPoint("旅游點(diǎn)1"); } /** * 入住酒店 * @return 返回true,說明還要繼續(xù)旅游,否則就臨時(shí)退出了 */ private boolean goToHotel() { return goToPoint("酒店"); } /** * 出發(fā)點(diǎn)集合 * @return 返回true,說明還要繼續(xù)旅游,否則就臨時(shí)退出了 */ private boolean goToStartingPoint() { return goToPoint("出發(fā)點(diǎn)"); } private int getRandomTime() throws InterruptedException { int time = random.nextInt(400) + 100; Thread.sleep(time); return time; } /** * @param point 集合點(diǎn) * @return 返回true,說明還要繼續(xù)旅游,否則就臨時(shí)退出了 */ private boolean goToPoint(String point){ try { if(!randomEvent()){ phaser.arriveAndDeregister(); return false; } String name = Thread.currentThread().getName(); System.out.println(name + " 花了 " + getRandomTime() + " 時(shí)間才到了" + point); phaser.arriveAndAwaitAdvance(); return true; } catch (Exception e) { e.printStackTrace(); } return false; } /** * 隨機(jī)事件 * @return 返回true,說明還要繼續(xù)旅游,否則就臨時(shí)退出了 */ private boolean randomEvent() { int r = random.nextInt(100); String name = Thread.currentThread().getName(); if (r < 10){ int friendNum = 1; System.out.println(name + ":在這里竟然遇到了"+friendNum+"個(gè)朋友,他們說要一起去旅游..."); phaser.bulkRegister(friendNum); for (int i = 0; i < friendNum; i ++){ new Thread(new TourismRunnable(phaser), name + "的朋友" + frientCount.getAndAdd(1) + "號(hào)").start(); } }else if(r > 90){ System.out.println(name + ":突然有事要離開一下,不和他們繼續(xù)旅游了...."); return false; } return true; } }
代碼解析
tourism這個(gè)方法的case寫法看起有點(diǎn)怪異,如果是為了滿足我們這個(gè)需求,這里的case的意思是-->case 第幾次集合: if(是否繼續(xù)旅游) 若不繼續(xù)則break,否則繼續(xù)后面的旅游
phaser.getPhase() 初始值為0,如果全部人到達(dá)集合點(diǎn)這個(gè)Phase+1,如果phaser.getPhase()達(dá)到Integer的最大值,這重新清空為0,在這里表示第幾次集合了
phaser.arriveAndDeregister(); 表示這個(gè)人旅游到這個(gè)景點(diǎn)之后,就離開這個(gè)旅游團(tuán)了
phaser.arriveAndAwaitAdvance(); 表示這個(gè)人在這個(gè)景點(diǎn)旅游完,在等待其他人
phaser.bulkRegister(friendNum); 表示這個(gè)人在這個(gè)景點(diǎn)遇到了friendNum個(gè)朋友,他們要加入一起旅游
最后我們的測(cè)試代碼還是差不多的,比例子1多了一個(gè)到齊后的操作
public class TestMain { public static void main(String[] args) { String name = "明剛紅麗黑白"; Phaser phaser = new SubPhaser(name.length()); ListtourismThread = new ArrayList<>(); for (char ch : name.toCharArray()){ tourismThread.add(new Thread(new TourismRunnable(phaser), "小" + ch)); } for (Thread thread : tourismThread){ thread.start(); } } public static class SubPhaser extends Phaser{ public SubPhaser(int parties) { super(parties); } @Override protected boolean onAdvance(int phase, int registeredParties) { System.out.println(Thread.currentThread().getName() + ":全部"+getArrivedParties()+"個(gè)人都到齊了,現(xiàn)在是第"+(phase + 1) +"次集合準(zhǔn)備去下一個(gè)地方.................. "); return super.onAdvance(phase, registeredParties); } } }
運(yùn)行輸出以下結(jié)果:
小白 花了 109 時(shí)間才到了出發(fā)點(diǎn) 小紅 花了 135 時(shí)間才到了出發(fā)點(diǎn) 小麗 花了 218 時(shí)間才到了出發(fā)點(diǎn) 小黑 花了 297 時(shí)間才到了出發(fā)點(diǎn) 小明 花了 303 時(shí)間才到了出發(fā)點(diǎn) 小剛 花了 440 時(shí)間才到了出發(fā)點(diǎn) 小剛:全部6個(gè)人都到齊了,現(xiàn)在是第1次集合準(zhǔn)備去下一個(gè)地方.................. 小明:突然有事要離開一下,不和他們繼續(xù)旅游了.... 小剛:突然有事要離開一下,不和他們繼續(xù)旅游了.... 小紅 花了 127 時(shí)間才到了酒店 小麗 花了 162 時(shí)間才到了酒店 小黑 花了 365 時(shí)間才到了酒店 小白 花了 474 時(shí)間才到了酒店 小白:全部4個(gè)人都到齊了,現(xiàn)在是第2次集合準(zhǔn)備去下一個(gè)地方.................. 小黑:突然有事要離開一下,不和他們繼續(xù)旅游了.... 小麗:突然有事要離開一下,不和他們繼續(xù)旅游了.... 小紅 花了 348 時(shí)間才到了旅游點(diǎn)1 小白 花了 481 時(shí)間才到了旅游點(diǎn)1 小白:全部2個(gè)人都到齊了,現(xiàn)在是第3次集合準(zhǔn)備去下一個(gè)地方.................. 小白 花了 128 時(shí)間才到了旅游點(diǎn)2 小紅 花了 486 時(shí)間才到了旅游點(diǎn)2 小紅:全部2個(gè)人都到齊了,現(xiàn)在是第4次集合準(zhǔn)備去下一個(gè)地方.................. 小紅 花了 159 時(shí)間才到了旅游點(diǎn)3 小白 花了 391 時(shí)間才到了旅游點(diǎn)3 小白:全部2個(gè)人都到齊了,現(xiàn)在是第5次集合準(zhǔn)備去下一個(gè)地方.................. 小白:在這里竟然遇到了1個(gè)朋友,他們說要一起去旅游... 小白 花了 169 時(shí)間才到了飛機(jī)場(chǎng),準(zhǔn)備登機(jī)回家 小紅 花了 260 時(shí)間才到了飛機(jī)場(chǎng),準(zhǔn)備登機(jī)回家 小白的朋友0號(hào) 花了 478 時(shí)間才到了飛機(jī)場(chǎng),準(zhǔn)備登機(jī)回家 小白的朋友0號(hào):全部3個(gè)人都到齊了,現(xiàn)在是第6次集合準(zhǔn)備去下一個(gè)地方..................
通過結(jié)果配合我上面的解釋,還是比較好理解的.
遺漏這里還有phaser的中斷和樹形結(jié)構(gòu)沒有舉例子,后續(xù)想到比較后的例子,我會(huì)繼續(xù)做補(bǔ)充的
后記這篇是我目前為止寫的最慢的一篇博文,因?yàn)橹皼]有使用過phaser,導(dǎo)致在寫的出現(xiàn)很多問題.所以一邊查資料,一邊學(xué)習(xí),總算還是把這個(gè)phaser給理解了.
打賞如果覺得我的文章寫的還過得去的話,有錢就捧個(gè)錢場(chǎng),沒錢給我捧個(gè)人場(chǎng)(幫我點(diǎn)贊或推薦一下)
java7 ?
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/69934.html
摘要:分層支持分層一種樹形結(jié)構(gòu),通過構(gòu)造函數(shù)可以指定當(dāng)前待構(gòu)造的對(duì)象的父結(jié)點(diǎn)。當(dāng)一個(gè)的參與者數(shù)量變成時(shí),如果有該有父結(jié)點(diǎn),就會(huì)將它從父結(jié)點(diǎn)中溢移除。當(dāng)首次將某個(gè)結(jié)點(diǎn)鏈接到樹中時(shí),會(huì)同時(shí)向該結(jié)點(diǎn)的父結(jié)點(diǎn)注冊(cè)一個(gè)參與者。 showImg(https://segmentfault.com/img/remote/1460000016010947); 本文首發(fā)于一世流云專欄:https://segme...
摘要:倒計(jì)時(shí)鎖,線程中調(diào)用使進(jìn)程進(jìn)入阻塞狀態(tài),當(dāng)達(dá)成指定次數(shù)后通過繼續(xù)執(zhí)行每個(gè)線程中剩余的內(nèi)容。實(shí)現(xiàn)分階段的的功能測(cè)試代碼拿客網(wǎng)站群三產(chǎn)創(chuàng)建于年月日。 同步器 為每種特定的同步問題提供了解決方案 Semaphore Semaphore【信號(hào)標(biāo);旗語】,通過計(jì)數(shù)器控制對(duì)共享資源的訪問。 測(cè)試類: package concurrent; import concurrent.th...
摘要:整個(gè)包,按照功能可以大致劃分如下鎖框架原子類框架同步器框架集合框架執(zhí)行器框架本系列將按上述順序分析,分析所基于的源碼為。后,根據(jù)一系列常見的多線程設(shè)計(jì)模式,設(shè)計(jì)了并發(fā)包,其中包下提供了一系列基礎(chǔ)的鎖工具,用以對(duì)等進(jìn)行補(bǔ)充增強(qiáng)。 showImg(https://segmentfault.com/img/remote/1460000016012623); 本文首發(fā)于一世流云專欄:https...
摘要:前言在前面的幾篇文章中詳述了框架的若干組分在相應(yīng)的官方文檔中總會(huì)不時(shí)地提起同樣的也提到可以用于幫助運(yùn)行在中的運(yùn)行時(shí)保持有效的執(zhí)行并行度其實(shí)特指其他都在等待一個(gè)的前進(jìn)時(shí)熟悉的朋友都知道它的大概組成部分包含支持并發(fā)的容器同步器線程池阻塞隊(duì)列原子 前言 在前面的幾篇文章中詳述了ForkJoin框架的若干組分,在相應(yīng)的官方文檔中總會(huì)不時(shí)地提起Phaser,同樣的,也提到Phaser可以用于幫助...
摘要:本人郵箱歡迎轉(zhuǎn)載轉(zhuǎn)載請(qǐng)注明網(wǎng)址代碼已經(jīng)全部托管有需要的同學(xué)自行下載引言自動(dòng)的兩個(gè)線程池講完今天就講跟他們有關(guān)的一個(gè)工具類吧理論僅僅是一個(gè)線程池的工具類它無法實(shí)例話包含都是靜態(tài)方法或靜態(tài)類創(chuàng)建一個(gè)指定線程數(shù)量的線程池創(chuàng)建一個(gè)可以自定義的線 本人郵箱: 歡迎轉(zhuǎn)載,轉(zhuǎn)載請(qǐng)注明網(wǎng)址 http://blog.csdn.net/tianshi_kcogithub: https://github.c...
閱讀 3253·2021-11-19 09:40
閱讀 3034·2021-09-09 09:32
閱讀 820·2021-09-02 09:55
閱讀 1417·2019-08-26 13:23
閱讀 2465·2019-08-26 11:46
閱讀 1256·2019-08-26 10:19
閱讀 2098·2019-08-23 16:53
閱讀 1103·2019-08-23 12:44