Java多線程ForkJoinPool實(shí)例詳解
引言
java 7提供了另外一個(gè)很有用的線程池框架,Fork/Join框架
理論
Fork/Join框架主要有以下兩個(gè)類組成.
* ForkJoinPool 這個(gè)類實(shí)現(xiàn)了ExecutorService接口和工作竊取算法(Work-Stealing Algorithm).它管理工作者線程,并提供任務(wù)的狀態(tài)信息,以及任務(wù)的執(zhí)行信息
* ForkJoinTask 這個(gè)類是一個(gè)將在ForkJoinPool執(zhí)行的任務(wù)的基類.
Fork/Join框架提供了在一個(gè)任務(wù)里執(zhí)行fork()和join()操作的機(jī)制和控制任務(wù)狀態(tài)的方法.通常,為了實(shí)現(xiàn)Fork/Join任務(wù),需要實(shí)現(xiàn)一個(gè)以下兩個(gè)類之一的子類
* RecursiveAction 用于任務(wù)沒有返回值的場景
* RecursiveTask 用于任務(wù)有返回值的場景.
例子 先定個(gè)小目標(biāo),1億就太多,先賺個(gè)一百萬吧
現(xiàn)在你是一個(gè)深圳片區(qū)的某公司高級銷售主管.現(xiàn)在定了一個(gè)目標(biāo),就是要賺個(gè)一百,讓你一個(gè)人去賺,肯定有難度的.好在有一般手下,把目標(biāo)縮小,讓小弟們?nèi)ベ?我們坐等拿錢.ok,開始編程
首先我們要定義個(gè)賺錢任務(wù) MakeMoneyTask,如果要賺錢的目標(biāo)小于最小目標(biāo),比如十萬,那么就自己去完成,否則,就把任務(wù)分給小弟們?nèi)プ?
public class MakeMoneyTask extends RecursiveTask<Integer>{ private static final int MIN_GOAL_MONEY = 100000; private int goalMoney; private String name; private static final AtomicLong employeeNo = new AtomicLong(); public MakeMoneyTask(int goalMoney){ this.goalMoney = goalMoney; this.name = "員工" + employeeNo.getAndIncrement() + "號"; } @Override protected Integer compute() { if (this.goalMoney < MIN_GOAL_MONEY){ System.out.println(name + ": 老板交代了,要賺 " + goalMoney + " 元,為了買車買房,加油吧...."); return makeMoney(); }else{ int subThreadCount = ThreadLocalRandom.current().nextInt(10) + 2; System.out.println(name + ": 上級要我賺 " + goalMoney + ", 有點(diǎn)小多,沒事讓我" + subThreadCount + "個(gè)手下去完成吧," + "每人賺個(gè) " + Math.ceil(goalMoney * 1.0 / subThreadCount) + "元應(yīng)該沒問題..."); List<MakeMoneyTask> tasks = new ArrayList<>(); for (int i = 0; i < subThreadCount; i ++){ tasks.add(new MakeMoneyTask(goalMoney / subThreadCount)); } Collection<MakeMoneyTask> makeMoneyTasks = invokeAll(tasks); int sum = 0; for (MakeMoneyTask moneyTask : makeMoneyTasks){ try { sum += moneyTask.get(); } catch (Exception e) { e.printStackTrace(); } } System.out.println(name + ": 嗯,不錯(cuò),效率還可以,終于賺到 " + sum + "元,趕緊邀功去...."); return sum; } } private Integer makeMoney(){ int sum = 0; int day = 1; try { while (true){ Thread.sleep(ThreadLocalRandom.current().nextInt(500)); int money = ThreadLocalRandom.current().nextInt(MIN_GOAL_MONEY / 3); System.out.println(name + ": 在第 " + (day ++) + " 天賺了" + money); sum += money; if (sum >= goalMoney){ System.out.println(name + ": 終于賺到 " + sum + " 元, 可以交差了..."); break; } } } catch (InterruptedException e) { e.printStackTrace(); } return sum; } }
最后我們寫一個(gè)測試類
public class TestMain { public static void main(String[] args) throws ExecutionException, InterruptedException { ForkJoinPool pool = new ForkJoinPool(); ForkJoinTask<Integer> task = pool.submit(new MakeMoneyTask(1000000)); do { try { TimeUnit.MILLISECONDS.sleep(5); }catch (InterruptedException e){ e.printStackTrace(); } }while (!task.isDone()); pool.shutdown(); System.out.println(task.get()); } }
運(yùn)作之后結(jié)果如下:
員工0號: 上級要我賺 1000000, 有點(diǎn)小多,沒事讓我10個(gè)手下去完成吧,每人賺個(gè) 100000.0元應(yīng)該沒問題… 員工1號: 上級要我賺 100000, 有點(diǎn)小多,沒事讓我7個(gè)手下去完成吧,每人賺個(gè) 14286.0元應(yīng)該沒問題… 員工11號: 老板交代了,要賺 14285 元,為了買車買房,加油吧…. 員工10號: 上級要我賺 100000, 有點(diǎn)小多,沒事讓我5個(gè)手下去完成吧,每人賺個(gè) 20000.0元應(yīng)該沒問題… 員工18號: 老板交代了,要賺 20000 元,為了買車買房,加油吧…. 員工9號: 上級要我賺 100000, 有點(diǎn)小多,沒事讓我3個(gè)手下去完成吧,每人賺個(gè) 33334.0元應(yīng)該沒問題… 員工23號: 老板交代了,要賺 33333 元,為了買車買房,加油吧…. 員工22號: 老板交代了,要賺 20000 元,為了買車買房,加油吧…. 員工22號: 在第 1 天賺了31432 員工22號: 終于賺到 31432 元, 可以交差了… 員工21號: 老板交代了,要賺 20000 元,為了買車買房,加油吧…. 員工18號: 在第 1 天賺了32005 員工18號: 終于賺到 32005 元, 可以交差了… 員工19號: 老板交代了,要賺 20000 元,為了買車買房,加油吧…. 員工23號: 在第 1 天賺了6166 員工21號: 在第 1 天賺了15433 員工19號: 在第 1 天賺了23419 員工19號: 終于賺到 23419 元, 可以交差了… 員工20號: 老板交代了,要賺 20000 元,為了買車買房,加油吧…. 員工20號: 在第 1 天賺了10376 員工11號: 在第 1 天賺了11808 員工21號: 在第 2 天賺了31059 員工21號: 終于賺到 46492 元, 可以交差了… 員工8號: 上級要我賺 100000, 有點(diǎn)小多,沒事讓我4個(gè)手下去完成吧,每人賺個(gè) 25000.0元應(yīng)該沒問題… 員工26號: 老板交代了,要賺 25000 元,為了買車買房,加油吧…. 員工11號: 在第 2 天賺了11902 員工11號: 終于賺到 23710 元, 可以交差了… 員工12號: 老板交代了,要賺 14285 元,為了買車買房,加油吧…. 員工23號: 在第 2 天賺了9077 員工20號: 在第 2 天賺了30386 員工20號: 終于賺到 40762 元, 可以交差了… 員工10號: 嗯,不錯(cuò),效率還可以,終于賺到 174110元,趕緊邀功去…. 員工7號: 上級要我賺 100000, 有點(diǎn)小多,沒事讓我10個(gè)手下去完成吧,每人賺個(gè) 10000.0元應(yīng)該沒問題… 員工30號: 老板交代了,要賺 10000 元,為了買車買房,加油吧…. 員工12號: 在第 1 天賺了31271 員工12號: 終于賺到 31271 元, 可以交差了… 員工26號: 在第 1 天賺了11631 員工13號: 老板交代了,要賺 14285 元,為了買車買房,加油吧…. 員工26號: 在第 2 天賺了10160 員工30號: 在第 1 天賺了10786 員工30號: 終于賺到 10786 元, 可以交差了… 員工31號: 老板交代了,要賺 10000 元,為了買車買房,加油吧…. 員工31號: 在第 1 天賺了15201 員工31號: 終于賺到 15201 元, 可以交差了… 員工32號: 老板交代了,要賺 10000 元,為了買車買房,加油吧…. 員工26號: 在第 3 天賺了32642 員工26號: 終于賺到 54433 元, 可以交差了… 員工27號: 老板交代了,要賺 25000 元,為了買車買房,加油吧…. 員工23號: 在第 3 天賺了33072 員工23號: 終于賺到 48315 元, 可以交差了… 員工24號: 老板交代了,要賺 33333 元,為了買車買房,加油吧…. 員工24號: 在第 1 天賺了26309 員工24號: 在第 2 天賺了15420 員工24號: 終于賺到 41729 元, 可以交差了… 員工25號: 老板交代了,要賺 33333 元,為了買車買房,加油吧…. 員工13號: 在第 1 天賺了33266 員工13號: 終于賺到 33266 元, 可以交差了… 員工14號: 老板交代了,要賺 14285 元,為了買車買房,加油吧…. 員工25號: 在第 1 天賺了19270 員工25號: 在第 2 天賺了15842 員工25號: 終于賺到 35112 元, 可以交差了… 員工9號: 嗯,不錯(cuò),效率還可以,終于賺到 125156元,趕緊邀功去…. 員工6號: 上級要我賺 100000, 有點(diǎn)小多,沒事讓我9個(gè)手下去完成吧,每人賺個(gè) 11112.0元應(yīng)該沒問題… 員工40號: 老板交代了,要賺 11111 元,為了買車買房,加油吧…. 員工32號: 在第 1 天賺了8133 員工32號: 在第 2 天賺了3518 員工32號: 終于賺到 11651 元, 可以交差了… 員工33號: 老板交代了,要賺 10000 元,為了買車買房,加油吧…. 員工27號: 在第 1 天賺了23200 員工14號: 在第 1 天賺了6366 員工27號: 在第 2 天賺了10406 員工27號: 終于賺到 33606 元, 可以交差了… 員工28號: 老板交代了,要賺 25000 元,為了買車買房,加油吧…. 員工40號: 在第 1 天賺了28078 員工40號: 終于賺到 28078 元, 可以交差了… 員工41號: 老板交代了,要賺 11111 元,為了買車買房,加油吧…. 員工41號: 在第 1 天賺了12996 員工41號: 終于賺到 12996 元, 可以交差了… 員工42號: 老板交代了,要賺 11111 元,為了買車買房,加油吧…. 員工33號: 在第 1 天賺了29188 員工33號: 終于賺到 29188 元, 可以交差了… 員工34號: 老板交代了,要賺 10000 元,為了買車買房,加油吧…. 員工14號: 在第 2 天賺了17712 員工14號: 終于賺到 24078 元, 可以交差了… 員工15號: 老板交代了,要賺 14285 元,為了買車買房,加油吧…. 員工28號: 在第 1 天賺了18623 員工28號: 在第 2 天賺了8205 員工28號: 終于賺到 26828 元, 可以交差了… 員工29號: 老板交代了,要賺 25000 元,為了買車買房,加油吧…. 員工34號: 在第 1 天賺了30779 員工34號: 終于賺到 30779 元, 可以交差了… 員工35號: 老板交代了,要賺 10000 元,為了買車買房,加油吧…. 員工42號: 在第 1 天賺了26164 員工42號: 終于賺到 26164 元, 可以交差了… 員工43號: 老板交代了,要賺 11111 元,為了買車買房,加油吧…. 員工43號: 在第 1 天賺了2995 員工29號: 在第 1 天賺了347 員工15號: 在第 1 天賺了33056 員工15號: 終于賺到 33056 元, 可以交差了… 員工16號: 老板交代了,要賺 14285 元,為了買車買房,加油吧…. 員工35號: 在第 1 天賺了3639 員工29號: 在第 2 天賺了22909 員工43號: 在第 2 天賺了2289 員工16號: 在第 1 天賺了27836 員工16號: 終于賺到 27836 元, 可以交差了… 員工17號: 老板交代了,要賺 14285 元,為了買車買房,加油吧…. 員工43號: 在第 3 天賺了694 員工17號: 在第 1 天賺了16361 員工17號: 終于賺到 16361 元, 可以交差了… 員工1號: 嗯,不錯(cuò),效率還可以,終于賺到 189578元,趕緊邀功去…. 員工2號: 上級要我賺 100000, 有點(diǎn)小多,沒事讓我2個(gè)手下去完成吧,每人賺個(gè) 50000.0元應(yīng)該沒問題… 員工49號: 老板交代了,要賺 50000 元,為了買車買房,加油吧…. 員工49號: 在第 1 天賺了8599 員工43號: 在第 4 天賺了10008 員工43號: 終于賺到 15986 元, 可以交差了… 員工44號: 老板交代了,要賺 11111 元,為了買車買房,加油吧…. 員工29號: 在第 3 天賺了31298 員工29號: 終于賺到 54554 元, 可以交差了… 員工8號: 嗯,不錯(cuò),效率還可以,終于賺到 169421元,趕緊邀功去…. 員工39號: 老板交代了,要賺 10000 元,為了買車買房,加油吧…. 員工49號: 在第 2 天賺了8099 員工35號: 在第 2 天賺了164 員工49號: 在第 3 天賺了5518 員工49號: 在第 4 天賺了22441 員工44號: 在第 1 天賺了6091 員工39號: 在第 1 天賺了18813 員工39號: 終于賺到 18813 元, 可以交差了… 員工48號: 老板交代了,要賺 11111 元,為了買車買房,加油吧…. 員工44號: 在第 2 天賺了22324 員工44號: 終于賺到 28415 元, 可以交差了… 員工45號: 老板交代了,要賺 11111 元,為了買車買房,加油吧…. 員工49號: 在第 5 天賺了28438 員工49號: 終于賺到 73095 元, 可以交差了… 員工50號: 老板交代了,要賺 50000 元,為了買車買房,加油吧…. 員工35號: 在第 3 天賺了31797 員工35號: 終于賺到 35600 元, 可以交差了… 員工36號: 老板交代了,要賺 10000 元,為了買車買房,加油吧…. 員工50號: 在第 1 天賺了18071 員工45號: 在第 1 天賺了22528 員工45號: 終于賺到 22528 元, 可以交差了… 員工46號: 老板交代了,要賺 11111 元,為了買車買房,加油吧…. 員工36號: 在第 1 天賺了26828 員工36號: 終于賺到 26828 元, 可以交差了… 員工37號: 老板交代了,要賺 10000 元,為了買車買房,加油吧…. 員工50號: 在第 2 天賺了32422 員工50號: 終于賺到 50493 元, 可以交差了… 員工2號: 嗯,不錯(cuò),效率還可以,終于賺到 123588元,趕緊邀功去…. 員工3號: 上級要我賺 100000, 有點(diǎn)小多,沒事讓我9個(gè)手下去完成吧,每人賺個(gè) 11112.0元應(yīng)該沒問題… 員工51號: 老板交代了,要賺 11111 元,為了買車買房,加油吧…. 員工46號: 在第 1 天賺了1537 員工46號: 在第 2 天賺了27529 員工46號: 終于賺到 29066 元, 可以交差了… 員工47號: 老板交代了,要賺 11111 元,為了買車買房,加油吧…. 員工48號: 在第 1 天賺了24791 員工48號: 終于賺到 24791 元, 可以交差了… 員工38號: 老板交代了,要賺 10000 元,為了買車買房,加油吧…. 員工37號: 在第 1 天賺了17587 員工37號: 終于賺到 17587 元, 可以交差了… 員工47號: 在第 1 天賺了23693 員工47號: 終于賺到 23693 元, 可以交差了… 員工6號: 嗯,不錯(cuò),效率還可以,終于賺到 211717元,趕緊邀功去…. 員工5號: 上級要我賺 100000, 有點(diǎn)小多,沒事讓我7個(gè)手下去完成吧,每人賺個(gè) 14286.0元應(yīng)該沒問題… 員工60號: 老板交代了,要賺 14285 元,為了買車買房,加油吧…. 員工51號: 在第 1 天賺了27189 員工51號: 終于賺到 27189 元, 可以交差了… 員工52號: 老板交代了,要賺 11111 元,為了買車買房,加油吧…. 員工38號: 在第 1 天賺了32285 員工38號: 終于賺到 32285 元, 可以交差了… 員工66號: 老板交代了,要賺 14285 元,為了買車買房,加油吧…. 員工7號: 嗯,不錯(cuò),效率還可以,終于賺到 228718元,趕緊邀功去…. 員工65號: 老板交代了,要賺 14285 元,為了買車買房,加油吧…. 員工65號: 在第 1 天賺了26122 員工65號: 終于賺到 26122 元, 可以交差了… 員工64號: 老板交代了,要賺 14285 元,為了買車買房,加油吧…. 員工52號: 在第 1 天賺了19239 員工52號: 終于賺到 19239 元, 可以交差了… 員工53號: 老板交代了,要賺 11111 元,為了買車買房,加油吧…. 員工60號: 在第 1 天賺了10433 員工66號: 在第 1 天賺了25993 員工66號: 終于賺到 25993 元, 可以交差了… 員工63號: 老板交代了,要賺 14285 元,為了買車買房,加油吧…. 員工60號: 在第 2 天賺了19529 員工60號: 終于賺到 29962 元, 可以交差了… 員工61號: 老板交代了,要賺 14285 元,為了買車買房,加油吧…. 員工64號: 在第 1 天賺了6894 員工53號: 在第 1 天賺了13114 員工53號: 終于賺到 13114 元, 可以交差了… 員工54號: 老板交代了,要賺 11111 元,為了買車買房,加油吧…. 員工54號: 在第 1 天賺了8237 員工61號: 在第 1 天賺了15878 員工61號: 終于賺到 15878 元, 可以交差了… 員工62號: 老板交代了,要賺 14285 元,為了買車買房,加油吧…. 員工63號: 在第 1 天賺了32108 員工63號: 終于賺到 32108 元, 可以交差了… 員工4號: 上級要我賺 100000, 有點(diǎn)小多,沒事讓我9個(gè)手下去完成吧,每人賺個(gè) 11112.0元應(yīng)該沒問題… 員工67號: 老板交代了,要賺 11111 元,為了買車買房,加油吧…. 員工64號: 在第 2 天賺了30531 員工64號: 終于賺到 37425 元, 可以交差了… 員工75號: 老板交代了,要賺 11111 元,為了買車買房,加油吧…. 員工54號: 在第 2 天賺了13562 員工54號: 終于賺到 21799 元, 可以交差了… 員工55號: 老板交代了,要賺 11111 元,為了買車買房,加油吧…. 員工55號: 在第 1 天賺了17774 員工55號: 終于賺到 17774 元, 可以交差了… 員工56號: 老板交代了,要賺 11111 元,為了買車買房,加油吧…. 員工67號: 在第 1 天賺了24463 員工67號: 終于賺到 24463 元, 可以交差了… 員工68號: 老板交代了,要賺 11111 元,為了買車買房,加油吧…. 員工56號: 在第 1 天賺了1677 員工62號: 在第 1 天賺了14266 員工75號: 在第 1 天賺了26532 員工75號: 終于賺到 26532 元, 可以交差了… 員工74號: 老板交代了,要賺 11111 元,為了買車買房,加油吧…. 員工68號: 在第 1 天賺了32639 員工68號: 終于賺到 32639 元, 可以交差了… 員工69號: 老板交代了,要賺 11111 元,為了買車買房,加油吧…. 員工69號: 在第 1 天賺了9513 員工56號: 在第 2 天賺了9154 員工56號: 在第 3 天賺了289 員工56號: 終于賺到 11120 元, 可以交差了… 員工57號: 老板交代了,要賺 11111 元,為了買車買房,加油吧…. 員工62號: 在第 2 天賺了17321 員工62號: 終于賺到 31587 元, 可以交差了… 員工5號: 嗯,不錯(cuò),效率還可以,終于賺到 199075元,趕緊邀功去…. 員工59號: 老板交代了,要賺 11111 元,為了買車買房,加油吧…. 員工69號: 在第 2 天賺了17971 員工69號: 終于賺到 27484 元, 可以交差了… 員工70號: 老板交代了,要賺 11111 元,為了買車買房,加油吧…. 員工74號: 在第 1 天賺了26270 員工74號: 終于賺到 26270 元, 可以交差了… 員工73號: 老板交代了,要賺 11111 元,為了買車買房,加油吧…. 員工70號: 在第 1 天賺了21237 員工70號: 終于賺到 21237 元, 可以交差了… 員工71號: 老板交代了,要賺 11111 元,為了買車買房,加油吧…. 員工59號: 在第 1 天賺了4411 員工57號: 在第 1 天賺了3546 員工57號: 在第 2 天賺了29330 員工57號: 終于賺到 32876 元, 可以交差了… 員工58號: 老板交代了,要賺 11111 元,為了買車買房,加油吧…. 員工73號: 在第 1 天賺了10674 員工71號: 在第 1 天賺了8821 員工59號: 在第 2 天賺了11887 員工59號: 終于賺到 16298 元, 可以交差了… 員工72號: 老板交代了,要賺 11111 元,為了買車買房,加油吧…. 員工58號: 在第 1 天賺了28241 員工58號: 終于賺到 28241 元, 可以交差了… 員工3號: 嗯,不錯(cuò),效率還可以,終于賺到 187650元,趕緊邀功去…. 員工72號: 在第 1 天賺了14371 員工72號: 終于賺到 14371 元, 可以交差了… 員工73號: 在第 2 天賺了14918 員工73號: 終于賺到 25592 元, 可以交差了… 員工71號: 在第 2 天賺了28814 員工71號: 終于賺到 37635 元, 可以交差了… 員工4號: 嗯,不錯(cuò),效率還可以,終于賺到 236223元,趕緊邀功去…. 員工0號: 嗯,不錯(cuò),效率還可以,終于賺到 1845236元,趕緊邀功去…. 1845236
看到?jīng)]有,員工0號把任務(wù)一百萬直接分給了10個(gè)手下去做,每個(gè)手下有繼續(xù)往下分,最終在七十幾號人的努力下,終于完成了目標(biāo)–一百萬.而且還超出八十多萬,老板一開心,直接把八十多萬分給這七十多個(gè)員工分紅了.
后記
通過上面這個(gè)例子的學(xué)習(xí),相信應(yīng)該很多人都可以掌握ForkJoinPool這個(gè)類,它的核心就是要完成某一個(gè)目標(biāo)任務(wù),如果目標(biāo)任務(wù)太大,那么就創(chuàng)建多個(gè)子任務(wù).然后一直等待這些子任務(wù)完成.最終完成之前定下的目標(biāo)任務(wù).
總結(jié)
以上就是本文關(guān)于Java多線程ForkJoinPool實(shí)例詳解的全部內(nèi)容,希望對大家有所幫助。歡迎各位參閱本站其他專題,有什么問題可以隨時(shí)留言,小編會及時(shí)回復(fù)大家的。
相關(guān)文章
Java傳入用戶名和密碼并自動提交表單實(shí)現(xiàn)登錄到其他系統(tǒng)的實(shí)例代碼
這篇文章主要介紹了Java傳入用戶名和密碼并自動提交表單實(shí)現(xiàn)登錄到其他系統(tǒng),非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2017-01-01Spring Cloud學(xué)習(xí)教程之DiscoveryClient的深入探究
這篇文章主要給大家介紹了關(guān)于Spring Cloud學(xué)習(xí)教程之DiscoveryClient的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧。2018-04-04Java面試為何阿里強(qiáng)制要求不在foreach里執(zhí)行刪除操作
那天,小二去阿里面試,面試官老王一上來就甩給了他一道面試題:為什么阿里的 Java 開發(fā)手冊里會強(qiáng)制不要在 foreach 里進(jìn)行元素的刪除操作2021-11-11java編程實(shí)現(xiàn)楊輝三角兩種輸出結(jié)果實(shí)例代碼
這篇文章主要介紹了java編程實(shí)現(xiàn)楊輝三角兩種輸出結(jié)果實(shí)例代碼,具有一定借鑒價(jià)值,需要的朋友可以參考下。2017-12-12Java語言中cas指令的無鎖編程實(shí)現(xiàn)實(shí)例
這篇文章主要介紹了Java語言中cas指令的無鎖編程實(shí)現(xiàn)實(shí)例,具有一定參考價(jià)值,需要的朋友可以了解下。2017-09-09Spring Kafka中@KafkaListener注解的參數(shù)與使用小結(jié)
@KafkaListener注解為開發(fā)者提供了一種聲明式的方式來定義消息監(jiān)聽器,本文主要介紹了Spring Kafka中@KafkaListener注解的參數(shù)與使用小結(jié),具有一定的參考價(jià)值,感興趣的可以了解一下2024-06-06