java中多线程之Executor

JAVA的Executor框架

Executor架构示意图

Executor接口

Executor接口是Executor框架中的最基础的部分,定义了一个用于执行Runnable的execute方法,他没有实现类,只有一个子接口ExecutorService

ExecutorService

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
public interface ExecutorService
extends Executor
{
/**
* 关闭方法,调用后执行之前提交的任务,不再接受新的任务
*/
public abstract void shutdown();
/**
* 将暂停所有等待处理的任务并返回这些任务的列表
*/
public abstract List shutdownNow();
/**
* 判断执行器是否已经关闭
*/
public abstract boolean isShutdown();
/**
* 关闭后所有任务是否都已完成
*/
public abstract boolean isTerminated();
/**
* 中断
*/
public abstract boolean awaitTermination(long l, TimeUnit timeunit)
throws InterruptedException;
/**
* 提交一个Callable任务
*/
public abstract Future submit(Callable callable);
public abstract Future submit(Runnable runnable, Object obj);
/**
* 提交一个Runable任务
*/
public abstract Future submit(Runnable runnable);
public abstract List invokeAll(Collection collection)
throws InterruptedException;
public abstract List invokeAll(Collection collection, long l, TimeUnit timeunit)
throws InterruptedException;
public abstract Object invokeAny(Collection collection)
throws InterruptedException, ExecutionException;
public abstract Object invokeAny(Collection collection, long l, TimeUnit timeunit)
throws InterruptedException, ExecutionException, TimeoutException;
}

ExecutorService接口继承自Executor接口,定义了终止、提交,执行任务、跟踪任务返回结果等方法

Executors

Executors提供生成各种类型的ExecutorService线程池实例

  • newFixedThreadPool:固定线程池,ExecutorService 创建一个固定线程数量的线程池,并行执行的线程数量不变,线程当前任务完成后,可以被重用执行另一个任务
  • newCachedThreadPool:可缓存线程池,ExecutorService 创建一个线程池,按需创建新线程,就是有任务时才创建,空闲线程保存60s,当前面创建的线程可用时,则重用它们
  • newSingleThreadExecutor:单线程执行器,线程池中只有一个线程,依次执行任务
  • newScheduledThreadPool:线程池按时间计划来执行任务,允许用户设定执行任务的时间
  • newSingleThreadScheduledExecutor:线程池中只有一个线程,它按规定时间来执行任务

Runnable Callable Futrue接口

Runnable和Callable的区别

  1. Callable的执行方法是call,runnable的执行方法是run
  2. Callable接口可以接收泛型,同时它执行任务后有返回值,而Runnable无返回值
  3. call方法可以抛出异常,run方法不可以

Futrue接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
// Future代表异步任务的执行结果
public interface Future<V> {
/**
* 尝试取消一个任务,如果这个任务不能被取消(通常是因为已经执行完了),返回false,否则返回true。
*/
boolean cancel(boolean mayInterruptIfRunning);
/**
* 返回代表的任务是否在完成之前被取消了
*/
boolean isCancelled();
/**
* 如果任务已经完成,返回true
*/
boolean isDone();
/**
* 获取异步任务的执行结果(如果任务没执行完将等待)
*/
V get() throws InterruptedException, ExecutionException;
/**
* 获取异步任务的执行结果(有最长等待时间的限制)
*
* timeout表示等待的时间,unit是它时间单位
*/
V get(long timeout, TimeUnit unit)
throws InterruptedException, ExecutionException, TimeoutException;
}

Future就是对于具体的Runnable或者Callable任务的执行结果进行取消、查询是否完成、获取结果。必要时可以通过get方法获取执行结果,该方法会阻塞直到任务返回结果

ThreadPoolExecutor

ThreadPoolExecutor是线程池的实现类

1
2
3
4
5
6
7
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler)

构造参数说明:

  • corePoolSize:核心线程数
  • maximumPoolSize: 线程池能容纳的最大线程数
  • keepAliveTime: 非核心线程闲置超时时间
  • unit: 指定超时时间单位,如TimeUnit.SECONDS
  • workQueue:线程池中的队列任务,常用的三种队列有SynchronousQueue,LinkedB lockingDeque,ArrayBlockingQueue线程工厂,提供创建新线程的功能。
  • ThreadFactor:通过线程工厂可以对线程的一些属性进行定制
  • RejectedExecutionHandler:当线程池中的资源已经全部使用,添加新线程被拒绝时,会调用RejectedExecutionHandler的rejectedExecution方法。

线程池执行示意图

提交线程的两种方式

  1. 通过execute()方法
  2. 通过submit()方法

参考资料

  1. JAVA 多线程 Executor框架的详解
  2. Java的Executor框架和线程池实现原理