前言
系列的最后一篇文章。线程池系列就算是暂时结束了。为什么说是暂时结束呢。学习一个东西。最快的方式就是直入主题。然而实际情况是,发现了更多之前不知道的知识点。然后去补之前的知识点。回过头在继续。就像是鱼骨图一样。笔者也是在学习的过程中发现了很多不足之处。
内卷的厉害啊!!!
系列文章
- 线程池系列 – (1)背景介绍
- 线程池系列 – (2)线程池的状态
- 线程池系列 – (3)拒绝策略
- 线程池系列 – (4)工作流程
- 线程池系列 – (5)shutdown && shutdownNow
- 线程池系列 – (6)submit
关系图
在分析submit之前。我们回到execute方法。我们知道他本质上就是一个接口

ExecutorService则是实现了Executor的接口。并且额外的增加了一些方法。submit等。而ExecutorService也是一个接口,如下图所示一样

这个接口的实现类则是 AbstractExecutorService.他是一个抽象类。具体实现了在ExecutorService中的接口方法。

真正继承了AbstractExecutorService的则是ThreadPoolExecutor

是不是很眼熟啊。没错。真是我们创建线程池时候的 ThreadPoolExecutor;可以看到。继承关系如下所示。

分析这样的类关系。更佳有助于我们理解与记忆线程池的设计。而不会迷失在代码当中
submit
线程池除了提供了一个基础的execute去执行线程。额外还提供了submit去执行线程。
为什么线程池要提供这样的几个方法去执行线程任务呢?
细心的小伙伴可能已经发现了。
execute执行的线程任务返回值是一个voidsubmit的返回值是一个Future
可能有小伙伴对 Future不了解。笔者这里做一个知识的补充
public interface Future<V> {
//取消任务。
// true 取消成功
// mayInterruptIfRunning:是否允许取消正在执行却没有执行完毕的任务
boolean cancel(boolean mayInterruptIfRunning);
//任务是否被取消成功
boolean isCancelled();
//任务是否已经完成
boolean isDone();
//获取执行结果,这个方法会产生阻塞,会一直等到任务执行完毕才返回
V get() throws InterruptedException, ExecutionException;
//用来获取执行结果,如果在指定时间内,还没获取到结果,就直接返回null
V get(long timeout, TimeUnit unit)
throws InterruptedException, ExecutionException, TimeoutException;
}
复制代码
通过上面的知识拓展。我们可以知道Future能够帮助我们
-
取消任务
-
获取任务状态
-
获取任务结果
有了这些知识拓展。在回头看一下 线程池 的submit方法。这个方法是在 ExecutorService 中。ExecutorService则是实现了Executor的接口。
public interface ExecutorService extends Executor {
<T> Future<T> submit(Callable<T> task);
<T> Future<T> submit(Runnable task, T result);
Future<?> submit(Runnable task);
//...省略代码
}
复制代码
回过头再看一下submit这3个方法。通过newTaskFor方法得到一个RunnableFuture在执行execute。嘿嘿。饶了一个圈,最终依然是执行execute。
/**
* @throws RejectedExecutionException {@inheritDoc}
* @throws NullPointerException {@inheritDoc}
*/
public Future<?> submit(Runnable task) {
if (task == null) throw new NullPointerException();
RunnableFuture<Void> ftask = newTaskFor(task, null);
execute(ftask);
return ftask;
}
/**
* @throws RejectedExecutionException {@inheritDoc}
* @throws NullPointerException {@inheritDoc}
*/
public <T> Future<T> submit(Runnable task, T result) {
if (task == null) throw new NullPointerException();
RunnableFuture<T> ftask = newTaskFor(task, result);
execute(ftask);
return ftask;
}
/**
* @throws RejectedExecutionException {@inheritDoc}
* @throws NullPointerException {@inheritDoc}
*/
public <T> Future<T> submit(Callable<T> task) {
if (task == null) throw new NullPointerException();
RunnableFuture<T> ftask = newTaskFor(task);
execute(ftask);
return ftask;
}
复制代码
总结
通过这样的接口设计。将职责分开。真正执行任务的地方只有一处execute。而拓展出来的其他方法。符合了设计原则中的开闭原则。对拓展开放,对修改关闭。可见线程池的设计是非常巧妙的。我们只需要关注这一个方法是如何运转的。就能够搞清楚线程池是如何工作的即可。



















![[02/27][官改] Simplicity@MIX2 ROM更新-一一网](https://www.proyy.com/wp-content/uploads/2020/02/3168457341.jpg)



![[桜井宁宁]COS和泉纱雾超可爱写真福利集-一一网](https://www.proyy.com/skycj/data/images/2020-12-13/4d3cf227a85d7e79f5d6b4efb6bde3e8.jpg)

![[桜井宁宁] 爆乳奶牛少女cos写真-一一网](https://www.proyy.com/skycj/data/images/2020-12-13/d40483e126fcf567894e89c65eaca655.jpg)