本文4300+字,实际文字大概300,建议阅读时间10分钟
我们知道Java预留了四种多线程池
其中一种为SingleThreadExecutor,如同其字面意思就是单线程池,看一下源码:
源码来自Executors类中静态方法
public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>()));
}
为了体现设计模式,我们再给出另一个线程池FixedThreadPool的源码
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
发现所有的预留多线程池只不过就是对不同参数的饿ThreadPoolExecutor的处理,值得提一下,如果你对ThreadPoolExecutor不熟悉的话,我贴出源码
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler)
省略构造方法体内容,只介绍两个参数:
corePoolSize 核心线程池大小
maximumPoolSize 最大线程池大小
我们希望刚才的newSingleThreadExecutor是单线程,其中corePoolSize = maximumPoolSize = 1 。
问题来了:如何设计保证线程池在运行中 corePoolSize和maximumPoolSize不变?
如果像FixedThreadPool那样设计会带来一个什么风险?
即直接返回一个ThreadPoolExecutor对象,用Service接口类接收的方式
如下图的继承关系可以直接通过强制类型转换,把ThreadPoolExecutor强制转换为ThreadPoolExecutor对象,通过set方法改变该值。
封装一个新的类FinalizableDelegatedExecutorService
public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>()));
}
给出FinalizableDelegatedExecutorService源码:
static class FinalizableDelegatedExecutorService
extends DelegatedExecutorService {
FinalizableDelegatedExecutorService(ExecutorService executor) {
super(executor);
}
protected void finalize() {
super.shutdown();
}
}
可以看出该内部类继承于DelegatedExecutorService,那么继续给出DelegatedExecutorService源码
static class DelegatedExecutorService extends AbstractExecutorService {
private final ExecutorService e;
DelegatedExecutorService(ExecutorService executor) { e = executor; }
public void execute(Runnable command) { e.execute(command); }
public void shutdown() { e.shutdown(); }
public List<Runnable> shutdownNow() { return e.shutdownNow(); }
public boolean isShutdown() { return e.isShutdown(); }
public boolean isTerminated() { return e.isTerminated(); }
public boolean awaitTermination(long timeout, TimeUnit unit)
throws InterruptedException {
return e.awaitTermination(timeout, unit);
}
public Future<?> submit(Runnable task) {
return e.submit(task);
}
public <T> Future<T> submit(Callable<T> task) {
return e.submit(task);
}
public <T> Future<T> submit(Runnable task, T result) {
return e.submit(task, result);
}
public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)
throws InterruptedException {
return e.invokeAll(tasks);
}
public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks,
long timeout, TimeUnit unit)
throws InterruptedException {
return e.invokeAll(tasks, timeout, unit);
}
public <T> T invokeAny(Collection<? extends Callable<T>> tasks)
throws InterruptedException, ExecutionException {
return e.invokeAny(tasks);
}
public <T> T invokeAny(Collection<? extends Callable<T>> tasks,
long timeout, TimeUnit unit)
throws InterruptedException, ExecutionException, TimeoutException {
return e.invokeAny(tasks, timeout, unit);
}
}
不要被这种代码吓到,看构造器:
DelegatedExecutorService(ExecutorService executor) { e = executor; }
把子类ThreadPoolExecutor隐式转为父类对象ExecutorService,在封装给成员变量e, 其中所有方法通过e来调用.并把e 私有,取消private方法,且DelegatedExecutorService和ThreadPoolExecutor无继承关系,仅都实现了接口ExecutorService,这样就消除了强制类型转换的可能。彻底的把ThreadPoolExecutor隐藏起来,这就是封装的体现
这种方法实现的原理
把SingleThreadExecutor(ThreadPoolExecutor的对象)封装在了一个FinalizableDelegatedExecutorService对象中,FinalizableDelegatedExecutorService父类DelegatedExecutorService包含有一个ExecutorService(接口)e对象, 而其本身也是ExecutorService(接口)对象,并且其实现了部分ThreadPoolExecutor功能(调用e对象),此外,去掉了set 和get 把e隐藏,无法改变e
这种方法既然不是相同子类,如何对上层无痛(没有感觉)?
都实现了ExecutorService接口,此外所有多线程池的返回都是ExecutorService接口对象。
多态性的体现