欧美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都是用于獲取線(xiàn)程執(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方法用來(lái)取消任務(wù),取消成功則返回true,取消失敗則返回false。參數(shù)mayInterruptIfRunning設(shè)置為false,表示不允許在線(xiàn)程運(yùn)行時(shí)中斷,設(shè)置為true則表示允許。具體可分為以下三種情況:

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

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

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

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

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

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

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

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

二、Future與FutureTask使用與分析

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

2、使用FutureTask時(shí),根據(jù)FutureTask的構(gòu)造函數(shù)可以看到FutureTask既可以接收Callable的實(shí)現(xiàn)類(lèi),也可以接收Runnable的實(shí)現(xiàn)類(lèi)。當(dāng)你傳入的是Callable的實(shí)現(xiàn)類(lèi)時(shí),可以獲取線(xiàn)程執(zhí)行的結(jié)果;傳入Runnable的實(shí)現(xiàn)類(lèi)時(shí),由于Runnable的實(shí)現(xiàn)沒(méi)有返回值,需要傳入一個(gè)你設(shè)置的線(xiàn)程完成標(biāo)識(shí),也就是result,然后當(dāng)線(xiàn)程結(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
  }
}

接下來(lái)我們看下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";
 // 線(xiàn)程運(yùn)行成功后把,返回你傳入的val值
 FutureTask<String> futureTaskRun = new FutureTask<String>(taskRun, val);
 // 線(xiàn)程運(yùn)行,返回線(xiàn)程執(zhí)行的結(jié)果
 FutureTask<String> futureTaskCall = new FutureTask<String>(taskCall);
 //聲明線(xiàn)程池
 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自定義線(xiàn)程執(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類(lèi)對(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ì)通過(guò)newTaskFor方法轉(zhuǎn)換成FutureTask對(duì)象,所以我們具體分析下上面代碼中的三種情況:

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

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

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

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

//你傳入的Runnable與Callable實(shí)現(xiàn)類(lèi)都會(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)類(lèi)
   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類(lèi)本身的run方法,就是執(zhí)行Runnable、Callable的實(shí)現(xiàn)類(lèi)并獲取返回結(jié)果的過(guò)程。

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

相關(guān)文章

最新評(píng)論