首頁  >  文章  >  Java  >  ThreadPoolExecutor執行緒池之submit方法

ThreadPoolExecutor執行緒池之submit方法

巴扎黑
巴扎黑原創
2017-06-26 11:33:072056瀏覽

jdk1.7.0_79 

##  在上一篇《ThreadPoolExecutor線程池原理及其execute方法》中提到了在執行緒池ThreadPoolExecutor的原理以及它的execute方法。本文解析ThreadPoolExecutor#submit。

  對於一個任務的執行有時我們不需要它回傳結果,但是有我們需要它的回傳執行結果。對於執行緒來講,如果不需要它回傳結果則實作Runnable,而如果需要執行結果的話則可以實作Callable。在執行緒池同樣execute提供一個不需要傳回結果的任務執行,而對於需要結果傳回的則可呼叫其submit方法。

  回顧ThreadPoolExecutor的繼承關係。

  

  在Executor介面中只定義了execute方法,而submit方法則是在ExecutorService介面中定義的。

  

//ExecutorServicepublic interface ExecutorService extends Executor {
  ...
  <T> Future<T> submit(Callable<T> task);
  <T> Future<T> submit(Runnable task, T result);
  <T> Future<T> submit(Runnable task);
  ...
}
  而在其子類別AbstractExecutorService實作了submit方法。

//AbstractExecutorServicepublic abstract class AbstractExecutorService implements ExecutorService {
  ...
  public <T> Future<T> submit(Callable<T> task) {
    if (task == null) throw new NullPointerException();
    RunnableFuture<T> ftask = newTaskFor(task);
    execute(ftask);
    return ftask;
  }
  public <T> Future<T> submit(Runnable task, T result) {
    if (task == null) throw new NullPointerException();
    RunnableFuture<T> ftask = newTaskFor(task);
    execute(ftask);
    return ftask;
  }
  public Future<?> submit(Runnable task) {
    if (task == null) throw new NullPointerExeption();
    RunnableFuture<Void> ftask = newTaskFor(task, null);
    execute(ftask);
    return ftask; 
  }
  ...
}
  在AbstractExecutorService實現的submit方法實際上是一個模板方法,定義了submit方法的演算法骨架,其execute交給了子類別。 (可以看到在許多原始碼中,模板方法模式被大量運用,有關模板方法模式可參考《模板方法模式》)

  儘管submit方法能提供線程執行的返回值,但只有實現了Callable才會有回傳值,而實作Runnable的執行緒則是沒有回傳值的,也就是說在上面的3個方法中,submit(Callable task)能取得到它的回傳值,submit(Runnable task, T result)能透過傳入的載體result間接獲得執行緒的回傳值或準確來說交給執行緒處理一下,而最後一個方法submit(Runnable task)則是沒有回傳值的,就算取得它的回傳值也是null 。

  以下給3個例子,來感受下submit方法。

  submit(Callable task)

package com.threadpoolexecutor;import java.util.concurrent.*;/**
 * ThreadPoolExecutor#sumit(Callable<T> task)
 * Created by yulinfeng on 6/17/17. */public class Sumit1 {public static void main(String[] args) throws ExecutionException, InterruptedException {
        Callable<String> callable = new Callable<String>() {public String call() throws Exception {
                System.out.println("This is ThreadPoolExetor#submit(Callable<T> task) method.");return "result";
            }
        };

        ExecutorService executor = Executors.newSingleThreadExecutor();
        Future<String> future = executor.submit(callable);
        System.out.println(future.get());
    }
}

#  submit(Runnable task,#  submit(Runnable task,

#  
submit(Runnable task,

#  submit(Runnable task, T result)

package com.threadpoolexecutor;import java.util.concurrent.ExecutionException;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.concurrent.Future;/**
 * ThreadPoolExecutor#submit(Runnable task, T result)
 * Created by yulinfeng on 6/17/17. */public class Submit2 {public static void main(String[] args) throws ExecutionException, InterruptedException {

        ExecutorService executor = Executors.newSingleThreadExecutor();
        Data data = new Data();
        Future<Data> future = executor.submit(new Task(data), data);
        System.out.println(future.get().getName());
    }
}class Data {
    String name;public String getName() {return name;
    }public void setName(String name) {this.name = name;
    }
}class Task implements Runnable {
    Data data;public Task(Data data) {this.data = data;
    }public void run() {
        System.out.println("This is ThreadPoolExetor#submit(Runnable task, T result) method.");
        data.setName("kevin");
    }
}

  

submit(Runnable task)

#

package com.threadpoolexecutor;import java.util.concurrent.ExecutionException;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.concurrent.Future;/**
 * ThreadPoolExecutor#sumit(Runnable runnables)
 * Created by yulinfeng on 6/17/17. */public class Submit {public static void main(String[] args) throws ExecutionException, InterruptedException {
        Runnable runnable = new Runnable() {public void run() {
                System.out.println("This is ThreadPoolExetor#submit(Runnable runnable) method.");
            }
        };

        ExecutorService executor = Executors.newSingleThreadExecutor();
        Future future = executor.submit(runnable);
        System.out.println(future.get());
    }
}
  透過上面的實例可以看到在呼叫submit(Runnable runnable)的時候是不需要其定義類型的,也就是說雖然在ExecutorService中對其定義的是泛型方法,而在AbstractExecutorService中則不是泛型方法,因為它沒有傳回值。 (有關Object、T、?這三者的區別,可參考《Java中的Object、T(泛型)、?區別》)。

  從上面的原始碼可以看到,這三者方法幾乎是一樣的,關鍵就在於:

###
RunnableFuture<T> ftask = newTaskFor(task);
execute(ftask);
######  它是如何將一個任務作為參數傳遞給了newTaskFor,然後呼叫execute方法,最後再回傳ftask的呢? ######
//AbstractExecutorService#newTaskForprotected <T> RunnableFuture<T> newTaskFor(Callable<T> callable) {
  return new FutureTask<T>(callable);
}
  protected <T> RunnableFuture<T> newTaskFor(Runnable runnable, T value) {
  return new FutureTask<T>(runnable, value);
}
######  看來是回傳了一個FutureTask實例,FutureTask實作了Future和Runnable介面。 Future介面是Java執行緒Future模式的實現,可用用來非同步運算,實作Runnable介面表示可以作為一個執行緒執行。 FutureTask實作了這兩個介面意味著它代表非同步計算的結果,同時可以作為一個執行緒交給Executor來執行。有關FutureTask放到下章來單獨解析。所以這篇文章對於執行緒池ThreadPoolExecutor執行緒池的submit方法解析並不完整,必須先了解Java執行緒的Future模式-《14.Java中的Future模式》。 ###

以上是ThreadPoolExecutor執行緒池之submit方法的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn