线程池

本文主要是说明线程池的几个类的关系。因为有些东西经常搞混。至于线程池的流程,原理,作用等信息,以后想写的时候再追加吧。

 

1. 线程池相关的类

线程池

Executor:

只有一个execute(Runnable command)方法;

ExecutorService:

对Executor接口进行了扩展,增加submit(Callable<T> task),关系线程池,执行一组任务等方法。

ExecutorService executor = ...;    // 线程池的生成

Executors:

它是一个线程池工厂类,里面提供了多个工开发人员快速使用的线程池,如newFixedThreadPool、newCachedThreadPool、newScheduledThreadPool等,此外它还可以返回一个包装过的ExecutorService,是线程池的配置不可以被更改。(通过调用unconfigurableExecutorService(ExecutorService executor))

TheadPoolExecutor:

创建线程池核心类。或许之前,你创建线程池的时候经常是直接调用Executors的静态方法,但是这个有弊端,你没有明确你对创建的线程池的需求,比如说核心线程数,最大线程数,线程工厂,排队对列等。我们再创建线程池的时候,应该使用TheadPoolExecutor这个类,使用它的构造方法,明确指定线程池配置的核心参数。这一点也是阿里巴巴开发规范手册中提到的。

Runnable、Callable:

为了后面需要,说明一下它们的不同点。

Runnable没有返回值,并且不可以抛出异常;Callable有返回值,并且可以抛出异常。

Future、FutureTask:

线程池提交完任务后,都会返回一个Future。下面,通过代码看一下它们的不同。

 1 interface ArchiveSearcher { String search(String target); }
 2  class App {
 3    ExecutorService executor = ...
 4    ArchiveSearcher searcher = ...
 5    void showSearch(final String target)
 6        throws InterruptedException {
 7      Future<String> future
 8        = executor.submit(new Callable<String>() {
 9          public String call() {
10              return searcher.search(target);
11          }});
12      displayOtherThings(); // do other things while searching
13      try {
14        displayText(future.get()); // use future
15      } catch (ExecutionException ex) { cleanup(); return; }
16    }
17  }

FutureTask实现了Future接口,它还实现了Runnable接口。上面的构造方法可以用下面的形式进行替换:

1  FutureTask<String> future =
2    new FutureTask<String>(new Callable<String>() {
3      public String call() {
4        return searcher.search(target);
5    }});
6  executor.execute(future);

(Future和FutureTask的代码,摘自java api 8)

CompletionService、ExecutorCompletionService:

顾名思义,完成服务,它依靠一个单独的Exetuor来执行任务,CompletionService只管理内部完成的队列任务。

我们看下面的示例:

使用ExecutorService

 1 ExecutorService executorService = Executors.newFixedThreadPool(4);
 2 List<Future> futures = new ArrayList<Future<Integer>>();
 3 futures.add(executorService.submit(A));
 4 futures.add(executorService.submit(B));
 5 futures.add(executorService.submit(C));
 6 futures.add(executorService.submit(D));
 7 
 8 Then we can iterate over the list to get the computed result of each future:
 9 for (Future future:futures) {
10     Integer result = future.get();     // 结果的顺序就是提交的顺序,taskB完成了,但是taskA未完成,那么就会在taskA那里阻塞到完成为止。
11     // rest of the code here.
12 }

使用CompletionService

 1 ExecutorService executorService = Executors.newFixedThreadPool(4);
 2         CompletionService executorCompletionService= new ExecutorCompletionService<>(executorService );
 3         //Then again we can submit the tasks and get the result like:
 4         executorCompletionService.submit(A);
 5         executorCompletionService.submit(B);
 6         executorCompletionService.submit(C);
 7         executorCompletionService.submit(D);
 8 
 9         for (int i=0; i<4; i++) {
10             Integer result = executorCompletionService.take().get();  // 哪个先完成就先获取哪个的结果,跟任务提交顺序无关。
11             // Some processing here
12         }

 

上一篇:Java线程池ExecutorService 代码备忘


下一篇:线程-1、创建线程的方式及实现