日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

Java多线程系列--“JUC线程池”06之 Callable和Future

發布時間:2023/12/3 java 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java多线程系列--“JUC线程池”06之 Callable和Future 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

轉載自??Java多線程系列--“JUC線程池”06之 Callable和Future

Callable 和 Future 簡介

  Callable 和 Future 是比較有趣的一對組合。當我們需要獲取線程的執行結果時,就需要用到它們。Callable用于產生結果,Future用于獲取結果。

1. Callable

Callable 是一個接口,它只包含一個call()方法。Callable是一個返回結果并且可能拋出異常的任務。

為了便于理解,我們可以將Callable比作一個Runnable接口,而Callable的call()方法則類似于Runnable的run()方法。

Callable的源碼如下:

public interface Callable<V> {V call() throws Exception; }

說明:從中我們可以看出Callable支持泛型。

?

2. Future

Future 是一個接口。它用于表示異步計算的結果。提供了檢查計算是否完成的方法,以等待計算的完成,并獲取計算的結果。

Future的源碼如下:

public interface Future<V> {// 試圖取消對此任務的執行。boolean cancel(boolean mayInterruptIfRunning)// 如果在任務正常完成前將其取消,則返回 true。boolean isCancelled()// 如果任務已完成,則返回 true。boolean isDone()// 如有必要,等待計算完成,然后獲取其結果。V get() throws InterruptedException, ExecutionException;// 如有必要,最多等待為使計算完成所給定的時間之后,獲取其結果(如果結果可用)。V get(long timeout, TimeUnit unit)throws InterruptedException, ExecutionException, TimeoutException; }

說明: Future用于表示異步計算的結果。它的實現類是FutureTask,在講解FutureTask之前,我們先看看Callable, Future, FutureTask它們之間的關系圖,如下:

說明
(01) RunnableFuture是一個接口,它繼承了Runnable和Future這兩個接口。RunnableFuture的源碼如下:

public interface RunnableFuture<V> extends Runnable, Future<V> {void run(); }

(02) FutureTask實現了RunnableFuture接口。所以,我們也說它實現了Future接口。

?

示例和源碼分析(基于JDK1.7.0_40)

我們先通過一個示例看看Callable和Future的基本用法,然后再分析示例的實現原理。

import java.util.concurrent.Callable; import java.util.concurrent.Future; import java.util.concurrent.Executors; import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutionException;class MyCallable implements Callable {@Override public Integer call() throws Exception {int sum = 0;// 執行任務for (int i=0; i<100; i++)sum += i;//return sum; return Integer.valueOf(sum);} }public class CallableTest1 {public static void main(String[] args) throws ExecutionException, InterruptedException{//創建一個線程池ExecutorService pool = Executors.newSingleThreadExecutor();//創建有返回值的任務Callable c1 = new MyCallable();//執行任務并獲取Future對象 Future f1 = pool.submit(c1);// 輸出結果System.out.println(f1.get()); //關閉線程池 pool.shutdown(); } }

運行結果

4950

結果說明
  在主線程main中,通過newSingleThreadExecutor()新建一個線程池。接著創建Callable對象c1,然后再通過pool.submit(c1)將c1提交到線程池中進行處理,并且將返回的結果保存到Future對象f1中。然后,我們通過f1.get()獲取Callable中保存的結果;最后通過pool.shutdown()關閉線程池。

?

1. submit()

submit()在java/util/concurrent/AbstractExecutorService.java中實現,它的源碼如下:

public <T> Future<T> submit(Callable<T> task) {if (task == null) throw new NullPointerException();// 創建一個RunnableFuture對象RunnableFuture<T> ftask = newTaskFor(task);// 執行“任務ftask” execute(ftask);// 返回“ftask”return ftask; }

說明:submit()通過newTaskFor(task)創建了RunnableFuture對象ftask。它的源碼如下:

protected <T> RunnableFuture<T> newTaskFor(Callable<T> callable) {return new FutureTask<T>(callable); }

?

2. FutureTask的構造函數

FutureTask的構造函數如下:

public FutureTask(Callable<V> callable) {if (callable == null)throw new NullPointerException();// callable是一個Callable對象this.callable = callable;// state記錄FutureTask的狀態this.state = NEW; // ensure visibility of callable }

?

3. FutureTask的run()方法

我們繼續回到submit()的源碼中。
在newTaskFor()新建一個ftask對象之后,會通過execute(ftask)執行該任務。此時ftask被當作一個Runnable對象進行執行,最終會調用到它的run()方法;ftask的run()方法在java/util/concurrent/FutureTask.java中實現,源碼如下:

public void run() {if (state != NEW ||!UNSAFE.compareAndSwapObject(this, runnerOffset,null, Thread.currentThread()))return;try {// 將callable對象賦值給c。Callable<V> c = callable;if (c != null && state == NEW) {V result;boolean ran;try {// 執行Callable的call()方法,并保存結果到result中。result = c.call();ran = true;} catch (Throwable ex) {result = null;ran = false;setException(ex);}// 如果運行成功,則將result保存if (ran)set(result);}} finally {runner = null;// 設置“state狀態標記”int s = state;if (s >= INTERRUPTING)handlePossibleCancellationInterrupt(s);} }

說明run()中會執行Callable對象的call()方法,并且最終將結果保存到result中,并通過set(result)將result保存。
   ? ?之后調用FutureTask的get()方法,返回的就是通過set(result)保存的值。

?


更多內容

1.?Java多線程系列--“JUC線程池”02之 線程池原理(一)

2.?Java多線程系列--“JUC線程池”03之 線程池原理(二)

3.?Java多線程系列--“JUC線程池”04之 線程池原理(三)

4.?Java多線程系列--“JUC線程池”05之 線程池原理(四)

5.?Java多線程系列--“JUC線程池”01之 線程池架構

6.?Java多線程系列目錄(共xx篇)


總結

以上是生活随笔為你收集整理的Java多线程系列--“JUC线程池”06之 Callable和Future的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。