声明

该系列文章只是记录本人回顾java多线程编程时候记录的笔记。文中所用语言并非严谨的专业术语(太严谨的术语其实本人也不会……)。难免有理解偏差的地方,欢迎指正。
另外,大神请绕路。不喜勿喷。
毕竟好记性不如烂笔头嘛,而且许多东西只要不是你经常用的最终都会一丢丢一丢丢地给忘记。

1 Excutor家族概览

上一篇 http://blog.csdn.net/hylexus/article/details/53456463 中介绍了java线程池的相关概念和基本用法。

然而在平时真正使用的时候往往不是自己手动创建线程池的。而是通过本节要介绍的ExcutorExcutorService来使用的。

以下是Excutor家族的主要成员

ExcutorService家族

2 成员介绍

2.1 Executors

Executors是一个专门为ExecutorExecutorServiceScheduledExecutorServiceThreadFactoryCallable等设计的工厂类。

2.2 ThreadPoolExecutor

ThreadPoolExecutor就是 上一篇文章 介绍的线程池。他是整个线程池的核心组件。

然而,在多数情况下,ThreadPoolExecutor的实例的创建并不是我们自己new的。
而是通过java.util.concurrent.Executors这个工厂类来创建的。Executors提供方法以快捷的创建三种常用的 ThreadPoolExecutor

  • 固定大小的线程池
1
2
3
4
public static ExecutorService newFixedThreadPool(int nThreads){}
public static ExecutorService newFixedThreadPool(
int nThreads, ThreadFactory threadFactory){
}
  • 单个线程的线程池
1
2
3
4
public static ExecutorService newSingleThreadExecutor(){}
public static ExecutorService newSingleThreadExecutor(
ThreadFactory threadFactory){
}
  • 按需创建新线程的线程池

maximumPoolSize为Integer.MAX_VALUE,队列类型为 SynchronousQueue.

1
2
3
4
public static ExecutorService newCachedThreadPool(){}
public static ExecutorService newCachedThreadPool(
ThreadFactory threadFactory){
}

2.3 ScheduledThreadPoolExecutor

简单理解就是可调度版的ThreadPoolExecutor。一般是用来执行周期性的可调度的任务的。

Executors提供方法以快捷的创建 ScheduledThreadPoolExecutor

1
2
3
4
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize){}
public static ScheduledExecutorService newScheduledThreadPool(
int corePoolSize, ThreadFactory threadFactory) {
}

2.4 Runnable、Callable

这两个接口表示可以被ScheduledThreadPoolExecutorThreadPoolExecutor执行的任务的抽象。

Excutors工厂中提供了将Runnable包装为Callable的方法:

1
2
public static Callable<Object> callable(Runnable task){}
public static <T> Callable<T> callable(Runnable task, T result) {}

2.5 Future、FutureTask

Future表示异步执行的任务的返回结果。FutureTask是Future接口的间接实现类。

其实FutureTask不仅实现了Future接口,同时还实现了Runnable接口。

FutureTask的状态:

  • 未启动:刚刚被创建,尚未调动run()方法的状态
  • 已启动:调用了run()方法
  • 已完成:run方法执行完毕

FutureTask类的常用方法:

  • get() : Waits if necessary for the computation to complete, and then retrieves its result.
    • 在未启动状态调用get()==>阻塞
    • 在已启动状态调用get()==>阻塞
    • 在已完成状态调用get()==>返回执行结果,或者抛出异常
  • cancel():取消执行
    • 在未启动状态调用cancel(),将导致该任务永远不会被执行。
    • 在已启动状态调用cancel(),将会使用中断该任务线程的方式来尝试取消任务的执行。
    • 在调用时如果该任务已经被终止、或已经完成或者由于一些原因无法终止该方法都将返回false.

2.6 Executor、ExecutorService

java.util.concurrent.Executor是一个可以执行提交给他的任务的对象的抽象接口。只包含一个方法:

1
void execute(Runnable command);

java.util.concurrent.ExecutorServiceExecutor的子接口,提供了更加丰富的接口方法。

3 简单示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
ExecutorService service = Executors.newFixedThreadPool(12);
Future<List<String>> future = service.submit(new Callable<List<String>>() {
@Override
public List<String> call() throws Exception {
// 模拟查询耗时3秒
Thread.sleep(3000);
return Arrays.asList("tom", "cat", "apache", "Spark", "Scala");
}
});
try {
List<String> list = future.get();
list.forEach(System.out::println);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
} finally {
service.shutdown();
}

参考资料

  • 《java并发编程的艺术》