线程池与Executor框架

线程池

线程池的实现原理

1)线程池判断核心线程池里的线程是否都在执行任务。如果不是,则创建一个新的工作线程来执行任务。如果核心线程池里的线程都在执行任务,则进入下个流程。

2)线程池判断工作队列是否已经满。如果工作队列没有满,则将新提交的任务存储在这个工作队列里。如果工作队列满了,则进入下个流程。

3)线程池判断线程池的线程是否都处于工作状态。如果没有,则创建一个新的工作线程来执行任务。如果已经满了,则交给饱和策略来处理这个任务。

 

线程池的创建

我们可以通过ThreadPoolExecutor来创建一个线程池。

new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime,

milliseconds,runnableTaskQueue, handler);

1)corePoolSize(线程池的基本大小)

2)runnableTaskQueue(任务队列)

a)ArrayBlockingQueue:是一个基于数组结构的有界阻塞队列,此队列按FIFO(先进先出)原则对元素进行排序。

b)LinkedBlockingQueue:一个基于链表结构的阻塞队列,此队列按FIFO排序元素,吞吐量通常要高于ArrayBlockingQueue。

c)SynchronousQueue:一个不存储元素的阻塞队列。每个插入操作必须等到另一个线程调用移除操作,否则插入操作一直处于阻塞状态,吞吐量通常要高于Linked-BlockingQueue

d)PriorityBlockingQueue:一个具有优先级的无限阻塞队列。

3)maximumPoolSize(线程池最大数量)

4)ThreadFactory:用于设置创建线程的工厂

5)RejectedExecutionHandler(饱和策略): 默认情况下是AbortPolicy

a)AbortPolicy:直接抛出异常。

b)CallerRunsPolicy:只用调用者所在线程来运行任务。

c)DiscardOldestPolicy:丢弃队列里最近的一个任务,并执行当前任务。

d)DiscardPolicy:不处理,丢弃掉。

6) keepAliveTime(线程活动保持时间)

7) TimeUnit(线程活动保持时间的单位)

向线程池提交任务

可以使用两个方法向线程池提交任务,分别为execute()和submit()方法。

execute()方法:用于提交不需要返回值的任务,所以无法判断任务是否被线程池执行成功。execute()方法输入的任务是一个Runnable类的实例。

 

submit()方法:用于提交需要返回值的任务。线程池会返回一个future类型的对象,通过这个

future对象可以判断任务是否执行成功,并且可以通过future的get()方法来获取返回值,get()方法会阻塞当前线程直到任务完成,而使用get(long timeout,TimeUnit unit)方法则会阻塞当前线程一段时间后立即返回,这时候有可能任务没有执行完。

关闭线程池

可以通过调用线程池的shutdown或shutdownNow方法来关闭线程池。

shutdownNow:首先将线程池的状态设置成STOP,然后尝试停止所有的正在执行或暂停任务的线程,并返回等待执行任务的列表

Shutdown:只是将线程池的状态设置成SHUTDOWN状态,然后中断所有没有正在执行任务的线程。

 

Executor框架

Executor框架的主要成员:ThreadPoolExecutor、ScheduledThreadPoolExecutor、

Future接口、Runnable接口、Callable接口和Executors。

ThreadPoolExecutor

通常使用工厂类Executors来创建。Executors可以创建3种类型的

ThreadPoolExecutor:SingleThreadExecutor、FixedThreadPool和CachedThreadPool。

FixedThreadPool

①CorePoolSize = maximumPoolSize = nThreads

②keepAliveTime=0L

③使用无界队列LinkedBlockingQueue

 

SingleThreadExecutor

①corePoolSize = maximumPoolSize = 1

②使用无界队列LinkedBlockingQueue

 

CachedThreadPool

①corePoolSize = 0

②maximumPoolSize = Integer.MAX_VALUE

③ keepAliveTime = 60L

④使用没有容量的SynchronousQueue

 

ScheduledThreadPoolExecutor

通常使用工厂类Executors来创建。Executors可以创建2种类型的ScheduledThreadPoolExecutor。

ScheduledThreadPoolExecutor

ScheduledThreadPoolExecutor的执行主要分为两大部分:

1)当调用ScheduledThreadPoolExecutor的scheduleAtFixedRate()方法或者scheduleWith-FixedDelay()方法时,会向ScheduledThreadPoolExecutor的DelayQueue添加一个实现了RunnableScheduledFutur接口的ScheduledFutureTask。

2)线程池中的线程从DelayQueue中获取ScheduledFutureTask,然后执行任务。

SingleThreadScheduledExecutor

DelayQueue封装了一个PriorityQueue,这个PriorityQueue会对队列中的Scheduled-

FutureTask进行排序。排序时,time小的排在前面(时间早的任务将被先执行)。如果两个ScheduledFutureTask的time相同,就比较sequenceNumber,sequenceNumber小的排在前面(也就是说,如果两个任务的执行时间相同,那么先提交的任务将被先执行)。

 

Future接口

Future接口和实现Future接口的FutureTask类用来表示异步计算的结果。

当我们把Runnable接口或Callable接口的实现类提交(submit)给ThreadPoolExecutor或

ScheduledThreadPoolExecutor时,ThreadPoolExecutor或ScheduledThreadPoolExecutor会向我们返回一个FutureTask对象。

 

(4)Runnable接口和Callable接口

Runnable接口和Callable接口的实现类,都可以被ThreadPoolExecutor或Scheduled-

ThreadPoolExecutor执行。它们之间的区别是Runnable不会返回结果,而Callable可以返回结果。

除了可以自己创建实现Callable接口的对象外,还可以使用工厂类Executors来把一个

Runnable包装成一个Callable。

FutureTask三种状态

1) 未启动

2) 已启动

3) 已完成

Cancel

get

未启动

不执行

阻塞到完成

已启动

(true)中断 false(无影响)

阻塞到完成

已完成

返回false

立即返回

猜你喜欢

转载自www.cnblogs.com/mercuryji/p/multithreading_executor.html