shell 获取命令执行结果_java高并发系列 第31天:获取线程执行结果,这6种方法你都知道?...
這是java高并發系列第31篇。
環境:jdk1.8。
java高并發系列已經學了不少東西了,本篇文章,我們用前面學的知識來實現一個需求:
在一個線程中需要獲取其他線程的執行結果,能想到幾種方式?各有什么優缺點?
結合這個需求,我們使用6種方式,來對之前學過的知識點做一個回顧,加深記憶。
方式1:Thread的join()方法實現
代碼:
package?com.itsoku.chat31;import?java.sql.Time;
import?java.util.concurrent.*;
/**
?*?跟著阿里p7學并發,微信公眾號:javacode2018
?*/
public?class?Demo1?{
????//用于封裝結果
????static?class?Result<T>?{
????????T?result;
????????public?T?getResult()?{
????????????return?result;
????????}
????????public?void?setResult(T?result)?{
????????????this.result?=?result;
????????}
????}
????public?static?void?main(String[]?args)?throws?ExecutionException,?InterruptedException?{
????????System.out.println(System.currentTimeMillis());
????????//用于存放子線程執行的結果
????????Result?result?=?new?Result<>();//創建一個子線程
????????Thread?thread?=?new?Thread(()?->?{try?{
????????????????TimeUnit.SECONDS.sleep(3);
????????????????result.setResult(10);
????????????}?catch?(InterruptedException?e)?{
????????????????e.printStackTrace();
????????????}
????????});
????????thread.start();//讓主線程等待thread線程執行完畢之后再繼續,join方法會讓當前線程阻塞
????????thread.join();//獲取thread線程的執行結果
????????Integer?rs?=?result.getResult();
????????System.out.println(System.currentTimeMillis());
????????System.out.println(System.currentTimeMillis()?+?":"?+?rs);
????}
}
輸出:
15667331626361566733165692
1566733165692:10
代碼中通過join方式阻塞了當前主線程,當thread線程執行完畢之后,join方法才會繼續執行。
此行結論有誤,請跳過:join的方式,只能阻塞一個線程,如果其他線程中也需要獲取thread線程的執行結果,join方法無能為力了。
關于join()方法和線程更詳細的使用,可以參考:線程的基本操作
方式2:CountDownLatch實現
代碼:
package?com.itsoku.chat31;import?java.util.concurrent.*;
/**
?*?跟著阿里p7學并發,微信公眾號:javacode2018
?*/
public?class?Demo2?{
????//用于封裝結果
????static?class?Result<T>?{
????????T?result;
????????public?T?getResult()?{
????????????return?result;
????????}
????????public?void?setResult(T?result)?{
????????????this.result?=?result;
????????}
????}
????public?static?void?main(String[]?args)?throws?ExecutionException,?InterruptedException?{
????????System.out.println(System.currentTimeMillis());
????????CountDownLatch?countDownLatch?=?new?CountDownLatch(1);
????????//用于存放子線程執行的結果
????????Demo1.Result?result?=?new?Demo1.Result<>();//創建一個子線程
????????Thread?thread?=?new?Thread(()?->?{try?{
????????????????TimeUnit.SECONDS.sleep(3);
????????????????result.setResult(10);
????????????}?catch?(InterruptedException?e)?{
????????????????e.printStackTrace();
????????????}finally?{
????????????????countDownLatch.countDown();
????????????}
????????});
????????thread.start();//countDownLatch.await()會讓當前線程阻塞,當countDownLatch中的計數器變為0的時候,await方法會返回
????????countDownLatch.await();//獲取thread線程的執行結果
????????Integer?rs?=?result.getResult();
????????System.out.println(System.currentTimeMillis());
????????System.out.println(System.currentTimeMillis()?+?":"?+?rs);
????}
}
輸出:
15667337204061566733723453
1566733723453:10
上面代碼也達到了預期效果,使用CountDownLatch可以讓一個或者多個線程等待一批線程完成之后,自己再繼續;CountDownLatch更詳細的介紹見:JUC中等待多線程完成的工具類CountDownLatch,必備技能
方式3:ExecutorService.submit方法實現
代碼:
package?com.itsoku.chat31;import?java.util.concurrent.*;
/**
?*?跟著阿里p7學并發,微信公眾號:javacode2018
?*/
public?class?Demo3?{
????public?static?void?main(String[]?args)?throws?ExecutionException,?InterruptedException?{
????????//創建一個線程池
????????ExecutorService?executorService?=?Executors.newCachedThreadPool();
????????System.out.println(System.currentTimeMillis());
????????Future?future?=?executorService.submit(()?->?{try?{
????????????????TimeUnit.SECONDS.sleep(3);
????????????}?catch?(InterruptedException?e)?{
????????????????e.printStackTrace();
????????????}return?10;
????????});//關閉線程池
????????executorService.shutdown();
????????System.out.println(System.currentTimeMillis());
????????Integer?result?=?future.get();
????????System.out.println(System.currentTimeMillis()?+?":"?+?result);
????}
}
輸出:
15667341199381566734119989
1566734122989:10
使用ExecutorService.submit方法實現的,此方法返回一個Future,future.get()會讓當前線程阻塞,直到Future關聯的任務執行完畢。
相關知識:
JAVA線程池,這一篇就夠了
JUC中的Executor框架詳解1
JUC中的Executor框架詳解2
方式4:FutureTask方式1
代碼:
package?com.itsoku.chat31;import?java.util.concurrent.*;
/**
?*?跟著阿里p7學并發,微信公眾號:javacode2018
?*/
public?class?Demo4?{
????public?static?void?main(String[]?args)?throws?ExecutionException,?InterruptedException?{
????????System.out.println(System.currentTimeMillis());
????????//創建一個FutureTask
????????FutureTask?futureTask?=?new?FutureTask<>(()?->?{try?{
????????????????TimeUnit.SECONDS.sleep(3);
????????????}?catch?(InterruptedException?e)?{
????????????????e.printStackTrace();
????????????}return?10;
????????});//將futureTask傳遞一個線程運行new?Thread(futureTask).start();
????????System.out.println(System.currentTimeMillis());//futureTask.get()會阻塞當前線程,直到futureTask執行完畢
????????Integer?result?=?futureTask.get();
????????System.out.println(System.currentTimeMillis()?+?":"?+?result);
????}
}
輸出:
15667363503141566736350358
1566736353360:10
代碼中使用FutureTask實現的,FutureTask實現了Runnable接口,并且內部帶返回值,所以可以傳遞給Thread直接運行,futureTask.get()會阻塞當前線程,直到FutureTask構造方法傳遞的任務執行完畢,get方法才會返回。關于FutureTask詳細使用,請參考:JUC中的Executor框架詳解1
方式5:FutureTask方式2
代碼:
package?com.itsoku.chat31;import?java.util.concurrent.ExecutionException;
import?java.util.concurrent.FutureTask;
import?java.util.concurrent.TimeUnit;
/**
?*?跟著阿里p7學并發,微信公眾號:javacode2018
?*/
public?class?Demo5?{
????public?static?void?main(String[]?args)?throws?ExecutionException,?InterruptedException?{
????????System.out.println(System.currentTimeMillis());
????????//創建一個FutureTask
????????FutureTask?futureTask?=?new?FutureTask<>(()?->?10);//將futureTask傳遞一個線程運行new?Thread(()?->?{try?{
????????????????TimeUnit.SECONDS.sleep(3);
????????????}?catch?(InterruptedException?e)?{
????????????????e.printStackTrace();
????????????}
????????????futureTask.run();
????????}).start();
????????System.out.println(System.currentTimeMillis());//futureTask.get()會阻塞當前線程,直到futureTask執行完畢
????????Integer?result?=?futureTask.get();
????????System.out.println(System.currentTimeMillis()?+?":"?+?result);
????}
}
輸出:
15667363199251566736319970
1566736322972:10
創建了一個FutureTask對象,調用futureTask.get()會阻塞當前線程,子線程中休眠了3秒,然后調用futureTask.run();當futureTask的run()方法執行完畢之后,futureTask.get()會從阻塞中返回。
注意:這種方式和方式4的不同點。
關于FutureTask詳細使用,請參考:JUC中的Executor框架詳解1
方式6:CompletableFuture方式實現
代碼:
package?com.itsoku.chat31;import?java.util.concurrent.CompletableFuture;
import?java.util.concurrent.ExecutionException;
import?java.util.concurrent.FutureTask;
import?java.util.concurrent.TimeUnit;
/**
?*?跟著阿里p7學并發,微信公眾號:javacode2018
?*/
public?class?Demo6?{
????public?static?void?main(String[]?args)?throws?ExecutionException,?InterruptedException?{
????????System.out.println(System.currentTimeMillis());
????????CompletableFuture?completableFuture?=?CompletableFuture.supplyAsync(()?->?{try?{
????????????????TimeUnit.SECONDS.sleep(3);
????????????}?catch?(InterruptedException?e)?{
????????????????e.printStackTrace();
????????????}return?10;
????????});
????????System.out.println(System.currentTimeMillis());//futureTask.get()會阻塞當前線程,直到futureTask執行完畢
????????Integer?result?=?completableFuture.get();
????????System.out.println(System.currentTimeMillis()?+?":"?+?result);
????}
}
輸出:
15667362053481566736205428
1566736208429:10
CompletableFuture.supplyAsync可以用來異步執行一個帶返回值的任務,調用completableFuture.get()
會阻塞當前線程,直到任務執行完畢,get方法才會返回。
關于CompletableFuture更詳細的使用見:JUC中工具類CompletableFuture,必備技能
java高并發系列目錄
第1天:必須知道的幾個概念
第2天:并發級別
第3天:有關并行的兩個重要定律
第4天:JMM相關的一些概念
第5天:深入理解進程和線程
第6天:線程的基本操作
第7天:volatile與Java內存模型
第8天:線程組
第9天:用戶線程和守護線程
第10天:線程安全和synchronized關鍵字
第11天:線程中斷的幾種方式
第12天JUC:ReentrantLock重入鎖
第13天:JUC中的Condition對象
第14天:JUC中的LockSupport工具類,必備技能
第15天:JUC中的Semaphore(信號量)
第16天:JUC中等待多線程完成的工具類CountDownLatch,必備技能
第17天:JUC中的循環柵欄CyclicBarrier的6種使用場景
第18天:JAVA線程池,這一篇就夠了
第19天:JUC中的Executor框架詳解1
第20天:JUC中的Executor框架詳解2
第21天:java中的CAS,你需要知道的東西
第22天:JUC底層工具類Unsafe,高手必須要了解
第23天:JUC中原子類,一篇就夠了
第24天:ThreadLocal、InheritableThreadLocal(通俗易懂)
第25天:掌握JUC中的阻塞隊列
第26篇:學會使用JUC中常見的集合,常看看!
第27天:實戰篇,接口性能提升幾倍原來這么簡單
第28天:實戰篇,微服務日志的傷痛,一并幫你解決掉
第29天:高并發中常見的限流方式
第30天:JUC中工具類CompletableFuture,必備技能
阿里p7一起學并發,公眾號:路人甲java,每天獲取最新文章!
總結
以上是生活随笔為你收集整理的shell 获取命令执行结果_java高并发系列 第31天:获取线程执行结果,这6种方法你都知道?...的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 组件化框架设计之阿里巴巴开源路由框架——
- 下一篇: Arduino小游戏集合(俄罗斯方块)