Runnable、Callable、Executor、Future、FutureTask關係解讀
在再度溫習Java5的併發程式設計的知識點時發現,首要的就是把Runnable、Callable、Executor、Future等的關係搞明白,遂有了下述小測試程式,通過這個例子上述三者的關係就一目瞭然了。
在java5以後,一個可以排程執行的執行緒單元可以有三種方式定義:
Thread、Runnable、Callable,其中Runnable實現的是void run()方法,Callable實現的是 V call()方法,並且可以返回執行結果,其中Runnable可以提交給Thread來包裝下,直接啟動一個執行緒來執行,而Callable則一般都是提交給ExecuteService來執行。
簡單來說,Executor就是Runnable和Callable的排程容器,Future就是對於具體的排程任務的執行結果進行檢視,最為關鍵的是Future可以檢查對應的任務是否已經完成,也可以阻塞在get方法上一直等待任務返回結果。Runnable和Callable的差別就是Runnable是沒有結果可以返回的,就算是通過Future也看不到任務排程的結果的。
- /**
- * 通過簡單的測試程式來試驗Runnable、Callable通過Executor來排程的時候與Future的關係
- */
- package com.hadoop.thread;
- import java.util.concurrent.Callable;
- import java.util.concurrent.ExecutorService;
- import java.util.concurrent.Executors;
- import java.util.concurrent.Future;
- public class RunnableAndCallable2Future {
- public static void main(String[] args) {
- // 建立一個執行任務的服務
- ExecutorService executor = Executors.newFixedThreadPool(3);
- try {
- //1.Runnable通過Future返回結果為空
- //建立一個Runnable,來排程,等待任務執行完畢,取得返回結果
- Future<?> runnable1 = executor.submit(new Runnable() {
- @Override
- public void run() {
- System.out.println("runnable1 running.");
- }
- });
- System.out.println("Runnable1:" + runnable1.get());
- // 2.Callable通過Future能返回結果
- //提交併執行任務,任務啟動時返回了一個 Future物件,
- // 如果想得到任務執行的結果或者是異常可對這個Future物件進行操作
- Future<String> future1 = executor.submit(new Callable<String>() {
- @Override
- public String call() throws Exception {
- // TODO Auto-generated method stub
- return "result=task1";
- }
- });
- // 獲得任務的結果,如果呼叫get方法,當前執行緒會等待任務執行完畢後才往下執行
- System.out.println("task1: " + future1.get());
- //3. 對Callable呼叫cancel可以對對該任務進行中斷
- //提交併執行任務,任務啟動時返回了一個 Future物件,
- // 如果想得到任務執行的結果或者是異常可對這個Future物件進行操作
- Future<String> future2 = executor.submit(new Callable<String>() {
- @Override
- public String call() throws Exception {
- try {
- while (true) {
- System.out.println("task2 running.");
- Thread.sleep(50);
- }
- } catch (InterruptedException e) {
- System.out.println("Interrupted task2.");
- }
- return "task2=false";
- }
- });
- // 等待5秒後,再停止第二個任務。因為第二個任務進行的是無限迴圈
- Thread.sleep(10);
- System.out.println("task2 cancel: " + future2.cancel(true));
- // 4.用Callable時丟擲異常則Future什麼也取不到了
- // 獲取第三個任務的輸出,因為執行第三個任務會引起異常
- // 所以下面的語句將引起異常的丟擲
- Future<String> future3 = executor.submit(new Callable<String>() {
- @Override
- public String call() throws Exception {
- throw new Exception("task3 throw exception!");
- }
- });
- System.out.println("task3: " + future3.get());
- } catch (Exception e) {
- System.out.println(e.toString());
- }
- // 停止任務執行服務
- executor.shutdownNow();
- }
- }
執行結果如下:
- runnable1 running.
- Runnable1:null
- task1: result=task1
- task2 running.
- task2 cancel: true
- Interrupted task2.
- java.util.concurrent.ExecutionException: java.lang.Exception: Bad flag value!
FutureTask則是一個RunnableFuture<V>,即實現了Runnbale又實現了Futrue<V>這兩個介面,另外它還可以包裝Runnable和Callable<V>,所以一般來講是一個符合體了,它可以通過Thread包裝來直接執行,也可以提交給ExecuteService來執行,並且還可以通過v get()返回執行結果,線上程體沒有執行完成的時候,主執行緒一直阻塞等待,執行完則直接返回結果。
- public class FutureTaskTest {
- /**
- * @param args
- */
- public static void main(String[] args) {
- Callable<String> task = new Callable<String>() {
- public String call() {
- System.out.println("Sleep start.");
- try {
- Thread.sleep(1000 * 10);
- } catch (InterruptedException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- System.out.println("Sleep end.");
- return "time=" + System.currentTimeMillis();
- }
- };
- //直接使用Thread的方式執行
- FutureTask<String> ft = new FutureTask<String>(task);
- Thread t = new Thread(ft);
- t.start();
- try {
- System.out.println("waiting execute result");
- System.out.println("result = " + ft.get());
- } catch (InterruptedException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- } catch (ExecutionException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- //使用Executors來執行
- System.out.println("=========");
- FutureTask<String> ft2 = new FutureTask<String>(task);
- Executors.newSingleThreadExecutor().submit(ft2);
- try {
- System.out.println("waiting execute result");
- System.out.println("result = " + ft2.get());
- } catch (InterruptedException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- } catch (ExecutionException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
- }
執行結果如下:
- waiting execute result
- Sleep start.
- Sleep end.
- result = time=1370844662537
- =========
- waiting execute result
- Sleep start.
- Sleep end.
- result = time=1370844672542
相關文章
- Runnable,Callable,Future關係淺析
- 搞懂Runnable Callable Future FutureTask 及應用
- 執行緒執行 之 Runnable Callable Future ,FutureTask ExcutorService概覽執行緒
- Java併發之Executor + Callable + FutureJava
- Java多執行緒之Callable,Future,FutureTaskJava執行緒
- Java多執行緒——Callable、Future和FutureTaskJava執行緒
- Java併發程式設計:Callable、Future和FutureTaskJava程式設計
- 大話Android多執行緒(四) Callable、Future和FutureTaskAndroid執行緒
- (十三) 說一下runnable 和 callable 有什麼區別?Future是什麼?
- Future,FutureTaskCallable關係
- Java多執行緒21:多執行緒下的其他元件之CyclicBarrier、Callable、Future和FutureTaskJava執行緒元件
- 在Java中使用Callable和FutureJava
- Java多執行緒-Callable和FutureJava執行緒
- java多執行緒程式設計,Thread,Runnable,Future相關知識Java執行緒程式設計thread
- Java併發程式設計非同步操作Future和FutureTaskJava程式設計非同步
- 深入解讀ESB與SOA的關係
- 解讀三角關係(ERP)(轉)
- Netty非同步Future原始碼解讀Netty非同步原始碼
- 溫故知新----執行緒之Runnable與Callable介面的本質區別執行緒
- openfile解讀以及和latch的一點關係
- 原始碼解讀之FutureTask如何實現最大等待時間原始碼
- 解讀數倉中的資料物件及相關關係物件
- Nebula Graph 原始碼解讀系列 | Vol.05 Scheduler 和 Executor 兩兄弟原始碼
- 12 Spark Streaming原始碼解讀之Executor容錯安全性Spark原始碼
- 客戶關係管理(CRM)是什麼?CRM定義最全解讀!
- 物件導向程式設計程式碼詳解(依賴關係,關聯關係,組合關係)物件程式設計
- [Flutter]Dart Future詳解FlutterDart
- 匿名內部類中關於new Runnable ( )
- Runnable jarJAR
- Java中「Future」介面詳解Java
- Java併發程式設計之Executor執行緒池原理與原始碼解讀Java程式設計執行緒原始碼
- PostgreSQL 原始碼解讀(16)- 查詢語句#1(基礎:關係代數)SQL原始碼
- lucene join解決父子關係索引索引
- depmod解決模組依賴關係
- 羅蘭米勒《親密關係》閱讀筆記筆記
- 【Oracle】-【插入讀取順序】-插入讀取之間的順序關係Oracle
- 關係
- Android FutureTask 分析Android