ExecutorService引发的血案(一)结构

时间:2022-09-20 07:26:21

最近使用了github上面的一个多线程下载的库 MultiThreadDownloader,发现挺好用。于是打开看了一下源码,发现了ExecutorService这个东西。之前多多少少接触到了这个东西,知道是java并发编程里面使用的,但是一直不是很了解所以花点时间看了一下。

下面这张图,就是ExecutorService的结构图

ExecutorService引发的血案(一)结构

(ScheduledThreadPoolExecutor稍微复杂一点,后面会介绍到。)

Executors

class 

这个类是一个工厂类,里面封装了很多构建`ExecutorService`实例的方法

public static ExecutorService newFixedThreadPool(int nThreads)

public static ExecutorService newSingleThreadExecutor() 

public static ExecutorService newCachedThreadPool(ThreadFactory threadFactory)

所以`ExecutorService`实例的构建一般都是通过`Executors`来构建的。

举例:

ExecutorService executorService1 = Executors.newSingleThreadExecutor();

ExecutorService executorService2 = Executors.newFixedThreadPool(10);

ExecutorService executorService3 = Executors.newScheduledThreadPool(10);

根据自己的需求创建不同的ExecutorService实例

Executor

interface

这个接口内部只有一个方法,也是这个结构中最核心的方法 `void execute(Runnable command)`

ExecutorService

interface 
继承`Executor`所以自然是有 `execute`方法的

这个接口对Executor再一次进行了加强添加了一些管理方法

void shutdown();

<T> Future<T> submit();

<T> List<Future<T>> invokeAll(……)
        throws InterruptedException;

<T> T invokeAny(……)
        throws InterruptedException, ExecutionException;

这些方法具体的使用后面将会讲到

AbstractExecutorService

classabstract

这个类是一个抽象类,规范了所有 工厂(Executors)构造的实例,也就是所有工厂构建的ExecutorService实例必须继承自AbstractExecutorService

看了上面的介绍大致可以看出ExecutorService外部的结构关系

那为什么要使用ExecutorService呢?

a. 每次new Thread新建对象性能差。
b. 线程缺乏统一管理,可能无限制新建线程,相互之间竞争,及可能占用过多系统资源导致死机或oom。
c. 缺乏更多功能,如定时执行、定期执行、线程中断。
相比new Thread,Java提供的四种线程池的好处在于:
a. 重用存在的线程,减少对象创建、消亡的开销,性能佳。
b. 可有效控制最大并发线程数,提高系统资源的使用率,同时避免过多资源竞争,避免堵塞。
c. 提供定时执行、定期执行、单线程、并发数控制等功能。

所以ExecutorService提供了一种线程调度机制,使我们更加方便系统的管理 Thread