Java中经过Executors调用静态方法来提供四种线程池介绍

Java中的线程池用ThreadPoolExecutor类来表示,ThreadPoolExecutor这个类继承自抽象类AbstractExecutorService,AbstractExecutorService又实现了ExecutorService接口,ExecutorService接口又继承了Executor接口。数组

ThreadPoolExecutor类详细说明在本博客中其余篇幅有介绍,若是须要请参考缓存

从参数即可以看到几个构造方式的不一样,可是若跟源码以后,会发现,前面三个都调用了第四个。安全

跟源码以后会发现,其实这些静态方法里面也是调用了ThreadPoolExecutor的构造方法,例如:数据结构

只不过Executors帮咱们配置了一些参数;下面介绍下Executors方式:并发

一、newCachedThreadPool 方法,它建立了一个可缓存的线程池,若是线程池的长度超过处理须要,它可灵活回收空闲线程,若无可回收,则新建线程。spa

2newScheduledThreadPool 方法,它建立了一个定长线程池,支持定时及周期性的任务执行。线程

三、newFixedThreadPool 方法,它建立了一个定长线程池,能够控制线程最大并发数,超出的线程会在队列中等待。继承

四、newSingleThreadExecutor 方法,它建立了一个单线程化的线程池,它只会用惟一的工做线程来执行任务,保证全部的任务按照指定的顺序(FIFO, LIFO, 优先级)来执行的。接口

 

1、newCachedThreadPool(能够缓存的线程池

首先,咱们一块儿来建立一个能够缓存的线程池,若是线程池的长度超过了处理须要的话,它可灵活的回收空闲的线程,若无可回收的线程,则就新建线程。代码如图1所示:生命周期

当前线程:pool-1-thread-1输出:0
当前线程:pool-1-thread-1输出:1
当前线程:pool-1-thread-1输出:2
当前线程:pool-1-thread-1输出:3
当前线程:pool-1-thread-1输出:4
当前线程:pool-1-thread-1输出:5
当前线程:pool-1-thread-1输出:6
当前线程:pool-1-thread-1输出:7
当前线程:pool-1-thread-1输出:8
当前线程:pool-1-thread-1输出:9

 

以上第一种方式建立线程池,线程池为无限大的,当其执行到第二个任务的时候,第一个任务已经完成了,而且会复用执行第一个任务的线程,进而不用每次新建线程。

改变下,去掉睡眠,注释掉,输出结果

//Thread.sleep(i*1000);

当前线程:pool-1-thread-1输出:0
当前线程:pool-1-thread-3输出:2
当前线程:pool-1-thread-3输出:9
当前线程:pool-1-thread-5输出:4
当前线程:pool-1-thread-7输出:6
当前线程:pool-1-thread-2输出:1
当前线程:pool-1-thread-9输出:8
当前线程:pool-1-thread-6输出:5
当前线程:pool-1-thread-8输出:7
当前线程:pool-1-thread-4输出:3
去掉休眠,这种方式将会建立1-10个线程,获取cup时间片执行

2、newScheduledThreadPool(定长的线程池)

而后,咱们一块儿来建立一个定长的线程池,这个线程池它支持定时及周期性的任务执行。延迟执行的示例代码如下图所示:表示延迟3秒执行代码。

当前线程:pool-1-thread-1输出:0
当前线程:pool-1-thread-1输出:2
当前线程:pool-1-thread-3输出:1
当前线程:pool-1-thread-3输出:4
当前线程:pool-1-thread-1输出:3
当前线程:pool-1-thread-2输出:5
当前线程:pool-1-thread-2输出:6
当前线程:pool-1-thread-2输出:7
当前线程:pool-1-thread-2输出:9
当前线程:pool-1-thread-4输出:8

以下图:表示延迟1秒后,每隔5秒执行一次代码即每隔5秒重复执行一次

当前线程:pool-1-thread-4输出:3
当前线程:pool-1-thread-1输出:0
当前线程:pool-1-thread-5输出:4
当前线程:pool-1-thread-2输出:1
当前线程:pool-1-thread-2输出:8
当前线程:pool-1-thread-2输出:9
当前线程:pool-1-thread-3输出:2
当前线程:pool-1-thread-5输出:7
当前线程:pool-1-thread-1输出:6
当前线程:pool-1-thread-4输出:5
当前线程:pool-1-thread-2输出:0
当前线程:pool-1-thread-1输出:3
当前线程:pool-1-thread-4输出:4
当前线程:pool-1-thread-5输出:2
当前线程:pool-1-thread-2输出:6
当前线程:pool-1-thread-2输出:8
当前线程:pool-1-thread-2输出:9
当前线程:pool-1-thread-3输出:1
当前线程:pool-1-thread-5输出:7
当前线程:pool-1-thread-4输出:5

3、newFixedThreadPool(定长的线程池

而后,咱们一块儿来建立一个定长的线程池,能够控制线程的最大并发数,超出的任务会在队列中等待。示例代码以下所示:

以上第三种方式建立线程池,由于线程池大小为4,每一个任务输出index后sleep 3秒,因此每3秒打印4个数字。

定长线程池的大小最好根据系统资源进行设置。如Runtime.getRuntime().availableProcessors()

4、newSingleThreadExecutor

最后,咱们一块儿来建立一个单线程化的线程池,单线程化的线程池,它只会用惟一的工做线程来执行任务,保证全部任务按照指定顺序(FIFO, LIFO, 优先级)来执行。示例代码如图:

当前线程:pool-1-thread-1输出:0
当前线程:pool-1-thread-1输出:1
当前线程:pool-1-thread-1输出:2
当前线程:pool-1-thread-1输出:3
当前线程:pool-1-thread-1输出:4
当前线程:pool-1-thread-1输出:5
当前线程:pool-1-thread-1输出:6
当前线程:pool-1-thread-1输出:7
当前线程:pool-1-thread-1输出:8
当前线程:pool-1-thread-1输出:9

代码的结果是依次输出的,就至关因而按顺序的执行了各个任务。

五.线程池也是有生命周期的

runState表示当前线程池的状态。

当线程池初始建立的时候,是running态。

当线程池处于shutdown态的时候,此线程池不可以接受新的任务,它会等待全部的任务执行完毕。

当线程池处于stop状态的时候,此线程不能接受新的任务,而且会去尝试终止正在执行的任务。

那线程池何时处于什么状态呢。当调用了shutdown()方法的时候就会处于shutdown状态,当调用了shutdownNow()方法的时候就会处于stop状态。

六.任务队列及拒绝措施

 

线程池中的线程是有数量限制的,根据任务类型来设置线程数量,若是是CPU密集型,则数量为NCPU+1,若是是IO密集型,则数量为2*NCPU,不少时候,为了安全性,仍是会设置上限,当新的任务来的时候,若是正常数量的线程都在用着,那么就用一个队列数据结构把新的任务缓存起来,如果新任务增加速度大于线程完成任务的速度,这时能够在线程数量尚未达到上限的时候建立新的线程来执行任务,但如果达到了上限并且任务缓存队列已经满了的话,则有必要采起拒绝措施,拒绝后续任务的到来。

这里有两个概念:

1)任务缓存队列(详细介绍在本博客其余篇幅有详细介绍,若有须要请参考

常有这四种状况,咱们选用一个东西的时候确定是根据它的某些特征。

A、ArrayBlockingQueue:基于数组的先进先出队列,此队列建立时必须指定大小。

B、PriorityBlockingQueue:基于优先级的队列。

C、LinkedBlockingQueue:基于链表的先进先出队列,若是建立时没有指定大小,则默认为Integer.MAX_VALUE。

D、synchronousQueue:这个队列比较特殊,它不会保存提交的任务,而是将直接新建一个线程来执行新的任务。

2)任务的拒绝措施:若是线程池中任务缓存队列已经满了而且线程池中线程数目达到maxmunPoolSize,若是还有任务来,就会采起任务拒绝策略,一般有一些四种策略。

A、ThreadPoolExecutor.AbortPolicy:丢弃任务并抛出RejectedExecutionException异常。

B、ThreadPoolExecutor.DiscardPolicy:也是丢弃任务,可是不抛出异常。

C、ThreadPoolExecutor.DiscardOldestPolicy:丢弃队列最前面的任务,而后从新尝试执行任务(重复此过程)

D、ThreadPoolExecutor.CallerRunsPolicy:由调用线程处理该任务

附录:返回ExecutorService接口

ExecutorService接口方法

ExecutorService实现类

顶层Executor接口的,最终在ThreadPoolExecutor里面有了具体的实现,这个方法就是用来让线程池执行某个任务的。

相关文章
相关标签/搜索