91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

詳解java中Future與FutureTask

發布時間:2020-07-17 15:58:45 來源:億速云 閱讀:161 作者:小豬 欄目:編程語言

小編這次要給大家分享的是詳解java中Future與FutureTask,文章內容豐富,感興趣的小伙伴可以來了解一下,希望大家閱讀完這篇文章之后能夠有所收獲。

Future與FutureTask都是用于獲取線程執行的返回結果。下面我們就對兩者之間的關系與使用進行一個大致的介紹與分析

一、Future與FutureTask介紹:

Future位于java.util.concurrent包下,它是一個接口

public interface Future<V> {
 boolean cancel(boolean mayInterruptIfRunning);
 boolean isCancelled();
 boolean isDone();
 V get() throws InterruptedException, ExecutionException;
 V get(long timeout, TimeUnit unit)
  throws InterruptedException, ExecutionException, TimeoutException;
}

Future接口中聲明了5個方法,下面介紹一下每個方法的作用:

cancel方法用來取消任務,取消成功則返回true,取消失敗則返回false。參數mayInterruptIfRunning設置為false,表示不允許在線程運行時中斷,設置為true則表示允許。具體可分為以下三種情況:

1、如果任務已經完成,則無論mayInterruptIfRunning為true還是false,都返回false,這是因為你要取消的任務已經完成,則認為取消任務失敗;

2、如果任務正在執行,則無論mayInterruptIfRunning為true還是false,都返回true。只不過mayInterruptIfRunning為true時線程會被中斷,false時線程不會被中斷會執行完。

3、如果任務還沒有執行,則無論mayInterruptIfRunning為true還是false,都返回true。

isCancelled方法用于判斷任務是否被取消成功,cancel方法成功則返回 true,反之則為false。

isDone用于判斷任務是否完成, 如果任務完成則返回true。任務完成包括正常結束、任務被取消、任務發生異常,都返回true

get()方法用來獲取執行結果,這個方法會產生阻塞,會一直等到任務執行完畢才返回;

get(long timeout, TimeUnit unit)用來獲取執行結果,如果在指定時間內,還沒獲取到結果,拋出 java.util.concurrent.TimeoutException 異常

FutureTask 實現了RunnableFuture接口,而RunnableFuture則繼承了Future<V>與Runnable接口,所以 FutureTask不僅實現了 Future<V>接口的所有方法,還具有自己的run方法,我們可以看下它的類圖

詳解java中Future與FutureTask

二、Future與FutureTask使用與分析

1、使用Future時,我們需要實現Callable接口,并通過ExecutorService接口的submit方法獲取返回的Future對象,

2、使用FutureTask時,根據FutureTask的構造函數可以看到FutureTask既可以接收Callable的實現類,也可以接收Runnable的實現類。當你傳入的是Callable的實現類時,可以獲取線程執行的結果;傳入Runnable的實現類時,由于Runnable的實現沒有返回值,需要傳入一個你設置的線程完成標識,也就是result,然后當線程結束時會把你傳入的result原值返回給你,FutureTask的構造函數具體如下:

public class FutureTask<V> implements RunnableFuture<V>{
  public FutureTask(Callable<V> callable) {
  if (callable == null)
   throw new NullPointerException();
  this.callable = callable;
  this.state = NEW;  // ensure visibility of callable
  }
  public FutureTask(Runnable runnable, V result) {
  this.callable = Executors.callable(runnable, result);//runnable轉化為callable 
  this.state = NEW;  // ensure visibility of callable
  }
}

接下來我們看下Future與FutureTask具體的使用代碼:

// 執行任務 實現Runnable
 FutureTaskJobRunnable taskRun = new FutureTaskJobRunnable();
 // 執行任務 實現Callable
 FutureTaskJobCallable taskCall = new FutureTaskJobCallable();
 String val = "ok";
 // 線程運行成功后把,返回你傳入的val值
 FutureTask<String> futureTaskRun = new FutureTask<String>(taskRun, val);
 // 線程運行,返回線程執行的結果
 FutureTask<String> futureTaskCall = new FutureTask<String>(taskCall);
 //聲明線程池
 ExecutorService executor = Executors.newCachedThreadPool();  
 //Future
 Future<String> future = executor.submit(taskCall);
 System.out.println(future.get());
 //FutureTask
 executor.submit(futureTaskCall);
 System.out.println(futureTaskCall.get());
 //FutureTask自定義線程執行
 new Thread(futureTaskRun).start();
 System.out.println(futureTaskRun.get());
public class FutureTaskJobCallable implements Callable<String>{
  
 public String call() throws Exception {
  System.out.println("FutureTaskJobCallable已經執行了哦");
  Thread.sleep(1000);
  return "返回結果";
 }
}
public class FutureTaskJobRunnable implements Runnable {
 public void run() {
  try {
   Thread.sleep(1000);
  } catch (InterruptedException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
  System.out.println("FutureTaskJobRunnable已經執行了哦");
 }
}

根據上面的代碼我們從ExecutorService接口中submit方法入手,看下AbstractExecutorService類對submit方法的具體實現。

public Future<&#63;> submit(Runnable task) {
  if (task == null) throw new NullPointerException();
  RunnableFuture<Void> ftask = newTaskFor(task, null);
  execute(ftask);
  return ftask;
 }
 public <T> Future<T> submit(Runnable task, T result) {
  if (task == null) throw new NullPointerException();
  RunnableFuture<T> ftask = newTaskFor(task, result);
  execute(ftask);
  return ftask;
 }
 public <T> Future<T> submit(Callable<T> task) {
  if (task == null) throw new NullPointerException();
  RunnableFuture<T> ftask = newTaskFor(task);
  execute(ftask);
  return ftask;
 }
 protected <T> RunnableFuture<T> newTaskFor(Runnable runnable, T value) {
  return new FutureTask<T>(runnable, value);
 }
 protected <T> RunnableFuture<T> newTaskFor(Callable<T> callable) {
  return new FutureTask<T>(callable);
 }

可以看到當你使用submit方法提交任務時,都會通過newTaskFor方法轉換成FutureTask對象,所以我們具體分析下上面代碼中的三種情況:

1、如果你傳入的是自己實現的Runaable類或者Callable類,那么sumbit方法自然會幫你自動封裝為FutureTask對象,運行后通過Future對象獲取結果。

2、你傳入的已經是個自己構造的FutureTask對象,由于FutureTask其實是實現了Runnable接口的,它本身就是個Runaable實現類, sumbit方法還是會將它視為Runnable類來進行封裝,并最終會執行FutureTask自己的run方法,一系列實現都在你傳入的FutureTask對象內完成,所以你可以直接通過自己構建的FutureTask獲取結果;

3、自己單獨聲明線程運行,跟第2點類似,FutureTask本身就是個Runnabel實現類,自然可以做為參數傳入Thread運行;

那么我們把自定義的Runnable、Callable實現類做為參數構造FutureTask后,FuttureTask是如何運行的呢,我們可以看下FuttureTask中具體的代碼實現

//你傳入的Runnable與Callable實現類都會在構造函數中轉化為Callable
private Callable<V> callable;
 public void run() {
  if (state != NEW ||
   !UNSAFE.compareAndSwapObject(this, runnerOffset,
           null, Thread.currentThread()))
   return;
  try {
   Callable<V> c = callable;//你傳入的實現類
   if (c != null && state == NEW) {
    V result;//返回值
    boolean ran;
    try {
     result = c.call();//運行后返回結果
     ran = true;
    } catch (Throwable ex) {
     result = null;
     ran = false;
     setException(ex);
    }
    if (ran)
     set(result);
   }
  } finally {
   // runner must be non-null until state is settled to
   // prevent concurrent calls to run()
   runner = null;
   // state must be re-read after nulling runner to prevent
   // leaked interrupts
   int s = state;
   if (s >= INTERRUPTING)
    handlePossibleCancellationInterrupt(s);
  }
 }

可以看到FutureTask類本身的run方法,就是執行Runnable、Callable的實現類并獲取返回結果的過程。

所以ExecutorService接口中submit方法歸根結底還是要把你傳入的對象封裝成FutureTask對象,并通過FutureTask類的內部實現來獲取結果的,返回的Future接口對象也要依賴于FutureTask實例化的,所以無論是直接傳入自己的Runnable、Callable實現類還是構建FutureTask傳入,本質上都是通過FutureTask去實現,沒有什么區別;

看完這篇關于詳解java中Future與FutureTask的文章,如果覺得文章內容寫得不錯的話,可以把它分享出去給更多人看到。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

朝阳县| 抚顺市| 文成县| 湄潭县| 宽甸| 泰安市| 横山县| 迁西县| 淮滨县| 来安县| 大石桥市| 溧阳市| 隆尧县| 龙门县| 五寨县| 金川县| 成安县| 海南省| 天镇县| 武鸣县| 辛集市| 进贤县| 文昌市| 平利县| 轮台县| 永济市| 芦溪县| 永新县| 浙江省| 全南县| 伊金霍洛旗| 改则县| 班玛县| 林州市| 金溪县| 珲春市| 哈尔滨市| 宜兰县| 岑巩县| 东山县| 乌审旗|