欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

比較java中Future與FutureTask之間的關(guān)系

 更新時(shí)間:2018年10月16日 14:21:05   投稿:laozhang  
在本篇文章里我們給大家分享了java中Future與FutureTask之間的關(guān)系的內(nèi)容,有需要的朋友們可以跟著學(xué)習(xí)下。

Future與FutureTask都是用于獲取線程執(zhí)行的返回結(jié)果。下面我們就對(duì)兩者之間的關(guān)系與使用進(jìn)行一個(gè)大致的介紹與分析

一、Future與FutureTask介紹:

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

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個(gè)方法,下面介紹一下每個(gè)方法的作用:

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

1、如果任務(wù)已經(jīng)完成,則無論mayInterruptIfRunning為true還是false,都返回false,這是因?yàn)槟阋∠娜蝿?wù)已經(jīng)完成,則認(rèn)為取消任務(wù)失??;

2、如果任務(wù)正在執(zhí)行,則無論mayInterruptIfRunning為true還是false,都返回true。只不過mayInterruptIfRunning為true時(shí)線程會(huì)被中斷,false時(shí)線程不會(huì)被中斷會(huì)執(zhí)行完。

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

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

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

get()方法用來獲取執(zhí)行結(jié)果,這個(gè)方法會(huì)產(chǎn)生阻塞,會(huì)一直等到任務(wù)執(zhí)行完畢才返回;

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

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

二、Future與FutureTask使用與分析

1、使用Future時(shí),我們需要實(shí)現(xiàn)Callable接口,并通過ExecutorService接口的submit方法獲取返回的Future對(duì)象,

2、使用FutureTask時(shí),根據(jù)FutureTask的構(gòu)造函數(shù)可以看到FutureTask既可以接收Callable的實(shí)現(xiàn)類,也可以接收Runnable的實(shí)現(xiàn)類。當(dāng)你傳入的是Callable的實(shí)現(xiàn)類時(shí),可以獲取線程執(zhí)行的結(jié)果;傳入Runnable的實(shí)現(xiàn)類時(shí),由于Runnable的實(shí)現(xiàn)沒有返回值,需要傳入一個(gè)你設(shè)置的線程完成標(biāo)識(shí),也就是result,然后當(dāng)線程結(jié)束時(shí)會(huì)把你傳入的result原值返回給你,F(xiàn)utureTask的構(gòu)造函數(shù)具體如下:

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轉(zhuǎn)化為callable 
  this.state = NEW;  // ensure visibility of callable
  }
}

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

// 執(zhí)行任務(wù) 實(shí)現(xiàn)Runnable
 FutureTaskJobRunnable taskRun = new FutureTaskJobRunnable();
 // 執(zhí)行任務(wù) 實(shí)現(xiàn)Callable
 FutureTaskJobCallable taskCall = new FutureTaskJobCallable();
 String val = "ok";
 // 線程運(yùn)行成功后把,返回你傳入的val值
 FutureTask<String> futureTaskRun = new FutureTask<String>(taskRun, val);
 // 線程運(yùn)行,返回線程執(zhí)行的結(jié)果
 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自定義線程執(zhí)行
 new Thread(futureTaskRun).start();
 System.out.println(futureTaskRun.get());
public class FutureTaskJobCallable implements Callable<String>{
  
 public String call() throws Exception {
  System.out.println("FutureTaskJobCallable已經(jīng)執(zhí)行了哦");
  Thread.sleep(1000);
  return "返回結(jié)果";
 }
}
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已經(jīng)執(zhí)行了哦");
 }
}

根據(jù)上面的代碼我們從ExecutorService接口中submit方法入手,看下AbstractExecutorService類對(duì)submit方法的具體實(shí)現(xiàn)。

public Future<?> 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);
 }

可以看到當(dāng)你使用submit方法提交任務(wù)時(shí),都會(huì)通過newTaskFor方法轉(zhuǎn)換成FutureTask對(duì)象,所以我們具體分析下上面代碼中的三種情況:

1、如果你傳入的是自己實(shí)現(xiàn)的Runaable類或者Callable類,那么sumbit方法自然會(huì)幫你自動(dòng)封裝為FutureTask對(duì)象,運(yùn)行后通過Future對(duì)象獲取結(jié)果。

2、你傳入的已經(jīng)是個(gè)自己構(gòu)造的FutureTask對(duì)象,由于FutureTask其實(shí)是實(shí)現(xiàn)了Runnable接口的,它本身就是個(gè)Runaable實(shí)現(xiàn)類, sumbit方法還是會(huì)將它視為Runnable類來進(jìn)行封裝,并最終會(huì)執(zhí)行FutureTask自己的run方法,一系列實(shí)現(xiàn)都在你傳入的FutureTask對(duì)象內(nèi)完成,所以你可以直接通過自己構(gòu)建的FutureTask獲取結(jié)果;

3、自己?jiǎn)为?dú)聲明線程運(yùn)行,跟第2點(diǎn)類似,F(xiàn)utureTask本身就是個(gè)Runnabel實(shí)現(xiàn)類,自然可以做為參數(shù)傳入Thread運(yùn)行;

那么我們把自定義的Runnable、Callable實(shí)現(xiàn)類做為參數(shù)構(gòu)造FutureTask后,F(xiàn)uttureTask是如何運(yùn)行的呢,我們可以看下FuttureTask中具體的代碼實(shí)現(xiàn)

//你傳入的Runnable與Callable實(shí)現(xiàn)類都會(huì)在構(gòu)造函數(shù)中轉(zhuǎn)化為Callable
private Callable<V> callable;
 public void run() {
  if (state != NEW ||
   !UNSAFE.compareAndSwapObject(this, runnerOffset,
           null, Thread.currentThread()))
   return;
  try {
   Callable<V> c = callable;//你傳入的實(shí)現(xiàn)類
   if (c != null && state == NEW) {
    V result;//返回值
    boolean ran;
    try {
     result = c.call();//運(yùn)行后返回結(jié)果
     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方法,就是執(zhí)行Runnable、Callable的實(shí)現(xiàn)類并獲取返回結(jié)果的過程。

所以ExecutorService接口中submit方法歸根結(jié)底還是要把你傳入的對(duì)象封裝成FutureTask對(duì)象,并通過FutureTask類的內(nèi)部實(shí)現(xiàn)來獲取結(jié)果的,返回的Future接口對(duì)象也要依賴于FutureTask實(shí)例化的,所以無論是直接傳入自己的Runnable、Callable實(shí)現(xiàn)類還是構(gòu)建FutureTask傳入,本質(zhì)上都是通過FutureTask去實(shí)現(xiàn),沒有什么區(qū)別;

相關(guān)文章

  • IDEA中thymeleaf語法沒有提示的問題及解決

    IDEA中thymeleaf語法沒有提示的問題及解決

    這篇文章主要介紹了IDEA中thymeleaf語法沒有提示的問題及解決,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-05-05
  • JAVA面試題之緩存擊穿、緩存穿透、緩存雪崩的三者區(qū)別

    JAVA面試題之緩存擊穿、緩存穿透、緩存雪崩的三者區(qū)別

    當(dāng)服務(wù)器QPS比較高,并且對(duì)數(shù)據(jù)的實(shí)時(shí)性要求不高時(shí),往往會(huì)接入緩存以達(dá)到快速Response、降低數(shù)據(jù)庫壓力的作用,常用來做緩存的中間件如Redis等。本文主要介紹了JAVA面試時(shí)常考的緩存擊穿、穿透、雪崩場(chǎng)景三者區(qū)別,有興趣的小伙伴可以看一下
    2021-11-11
  • Sa-Token不同模式實(shí)現(xiàn)單地登錄?多地登錄?同端互斥登錄

    Sa-Token不同模式實(shí)現(xiàn)單地登錄?多地登錄?同端互斥登錄

    這篇文章主要為大家介紹了Sa-Token不同模式實(shí)現(xiàn)單地登錄?多地登錄?同端互斥登錄,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-07-07
  • 解析springboot整合谷歌開源緩存框架Guava Cache原理

    解析springboot整合谷歌開源緩存框架Guava Cache原理

    本文主要為大家解析了springboot整合谷歌開源緩存框架Guava Cache的原理以及在實(shí)際開發(fā)過程中的使用,附含源碼,有需要的朋友可以參考下
    2021-08-08
  • Spring?BeanPostProcessor后處理器源碼解析

    Spring?BeanPostProcessor后處理器源碼解析

    這篇文章主要介紹了Spring?BeanPostProcessor后處理器源碼解析,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧
    2023-09-09
  • Spring中的事務(wù)隔離級(jí)別的介紹

    Spring中的事務(wù)隔離級(jí)別的介紹

    今天小編就為大家分享一篇關(guān)于Spring中的事務(wù)隔離級(jí)別的介紹,小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧
    2019-01-01
  • Springboot把外部依賴包納入Spring容器管理的兩種方式

    Springboot把外部依賴包納入Spring容器管理的兩種方式

    這篇文章主要給大家介紹了Springboot把外部依賴包納入Spring容器管理的兩種方式,Spring.factories和org.springframework.boot.autoconfigure.AutoConfiguration.imports,有感興趣的小伙伴可以參考閱讀本文
    2023-07-07
  • Android開發(fā)中實(shí)現(xiàn)用戶注冊(cè)和登陸的代碼實(shí)例分享

    Android開發(fā)中實(shí)現(xiàn)用戶注冊(cè)和登陸的代碼實(shí)例分享

    這篇文章主要介紹了Android開發(fā)中實(shí)現(xiàn)用戶注冊(cè)和登陸的代碼實(shí)例分享,只是實(shí)現(xiàn)基本功能,界面華麗度就請(qǐng)忽略啦XD 需要的朋友可以參考下
    2015-12-12
  • 解決mybatis-plus 查詢耗時(shí)慢的問題

    解決mybatis-plus 查詢耗時(shí)慢的問題

    這篇文章主要介紹了解決mybatis-plus 查詢耗時(shí)慢的問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-07-07
  • Java實(shí)現(xiàn)猜字小游戲

    Java實(shí)現(xiàn)猜字小游戲

    這篇文章給大家分享小編隨手寫的猜字小游戲,基于java代碼寫的,感興趣的朋友跟隨小編一起看看吧
    2019-11-11

最新評(píng)論