线程池(知识点)

固定线程池

public static ExecutorService newFixdThreadPool(int size);

此方法产生一个具有固定大小的线程池、如果有线程异常中止,将产生新的线程来替代他,参数size用来给出线程池的大小。

public static ExecutorService newSingleThreadExecutor();

此方法创建一个线程池,有点像newFixdThreadPool(1),在同一个时刻只可以执行一个任务,使用其可以保证多个任务是顺序执行的,并且其不可以被重新配置为支持多个线程。如果该线程异常中止,将产生新的线程来替代他。

上述两个方法返回的都是ExecutorService接口类型的引用。其实,此引用指向的就是线程池对象,可以通过ExecutorService引用调用其execute方法来使用线程池中的线程执行指定的任务,下面给出execute方法详细参数:

public void execute(Runnable command);

command参数指向实现了Runnable接口对象,次对象run方法中的代码描述了要执行的任务。

 

如果希望程序在执行完所有任务后退出,需要调用ExecutorService接口中的shutdown方法来关闭线程池,下面列出了两个关闭线程池的方法:

public void shutdown();

此方法关闭线程池,不再接受新的任务,等待旧结束则关闭所有池中线程。

public void shutdownNow();

此方法无论是否所有任务执行结束,立即关闭线程池,List中为等待执行的任务。


可变尺寸线程池

public static ExecutorService newCacheTheadPool();

此方法将创建一个线程池,线程池的大小不定,当执行任务时先选取重用缓存中已有空闲线程来完成任务,如果没有空闲线程,则创建新线程,空闲超过60秒的线程将被从线程池中删除。


延迟线程池

在实际开发中有时需要让指定在特定的时延之后执行,使用Java中提供的延迟线程池可以很好的满足这种需求。同样,延迟线程池也是通过调用Executor类的静态工厂方法来创建,下面列出了创建延迟线程池的两个静态方法:

public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize);

此方法创建一个线程池,可以以一定的时延执行指定的任务,参数corePoolSize用于指出线程池中的线程数量。

public static ScheduledExecutorService newSingleThreadScheduledExecutor();

此方法用于创建延迟的单线程线程池,也就是说用此方法创建的延迟线程池中只有一个待命的线程。

ScheduledExecutorService 接口继承了ExecuteService接口,具有ExecuteService接口的所有方法。

ScheduledExecutorService 接口具有其特有的schedule方法来延迟执行指定的任务:

public ScheduledFuture schedule(Runnable runnable,long delay,TimeUnit unit);

此方法调动线程池中的线程,以一定的时延的执行指定的任务,参数runnable表示要执行的任务,delay参数是时延的长度,unit参数表示时延的时间单位。此方法的返回值类型为ScheduledFuture,用来存放有返回结果的任务的结果信息。


自定义参数线程池

如果上述几种线程池不能满足我们的需要,我们可以考虑使用ThreadPoolExecutor类来实现自定义的线程池,其内置了一个线程队列(BlockingQueue)。

ThreadPoolExecutor 的继承关系如下

Executor->ExecutorService->AbstractExecutorService->ThreadPoolExecutor

核心池大小 (core pool size) 、最大池的大小 (maximum pool size) 、存活时间 (keep-alive time) 共同管理着线程的创建和销毁。

线程池类为 java.util.concurrent.ThreadPoolExecutor ,常用构造方法为:

public ThreadPoolExecutor( int corePoolSize, 

int maximumPoolSize, 

long keepAliveTime, 

TimeUnit unit, 

BlockingQueue<Runnable> workQueue, 

RejectedExecutionHandler handler) { 

this (corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, 

Executors. defaultThreadFactory (), handler); 

} 

 corePoolSize :线程池维护线程的最少数量,哪怕是空闲的。

maximumPoolSize :线程池维护线程的最大数量。

keepAliveTime :线程池维护线程所允许的空闲时间。

unit :线程池维护线程所允许的空闲时间的单位。

workQueue :线程池所使用的缓冲队列,改缓冲队列的长度决定了能够缓冲的最大数量。

拒绝任务:拒绝任务是指当线程池里面的线程数量达到 maximumPoolSize workQueue 队列已满的情况下被尝试添加进来的任务。

handler :线程池对拒绝任务的处理策略。在 ThreadPoolExecutor 里面定义了 4 handler 策略,分别是

1. CallerRunsPolicy :这个策略重试添加当前的任务,他会自动重复调用 execute() 方法,直到成功。

2. AbortPolicy :对拒绝任务抛弃处理,并且抛出异常。

3. DiscardPolicy :对拒绝任务直接无声抛弃,没有异常信息。

4. DiscardOldestPolicy :对拒绝任务不抛弃,而是抛弃队列里面等待最久的一个线程,然后把拒绝任务加到队列。

 

一个任务通过 execute(Runnable) 方法被添加到线程池,任务就是一个 Runnable 类型的对象,任务的执行方法就是 Runnable 类型对象的 run() 方法。

当一个任务通过 execute(Runnable) 方法欲添加到线程池时,线程池采用的策略如下:

1. 如果此时线程池中的数量小于 corePoolSize ,即使线程池中的线程都处于空闲状态,也要创建新的线程来处理被添加的任务。

2. 如果此时线程池中的数量等于 corePoolSize ,但是缓冲队列 workQueue 未满,那么任务被放入缓冲队列。

3. 如果此时线程池中的数量大于 corePoolSize ,缓冲队列 workQueue 满,并且线程池中的数量小于 maximumPoolSize ,建新的线程来处理被添加的任务。

4. 如果此时线程池中的数量大于 corePoolSize ,缓冲队列 workQueue 满,并且线程池中的数量等于 maximumPoolSize ,那么通过 handler 所指定的策略来处理此任务。

处理任务的优先级为:

核心线程 corePoolSize 、任务队列 workQueue 、最大线程 maximumPoolSize ,如果三者都满了,使用 handler 处理被拒绝的任务。当线程池中的线程数量大于 corePoolSize 时,如果某线程空闲时间超过 keepAliveTime ,线程将被终止。这样,线程池可以动态的调整池中的线程数。

理解了上面关于 ThreadPoolExecutord 的介绍,应该就基本能了解它的一些使用,不过在 ThreadPoolExocutor 里面有个关键的 Worker 类,所有的线程都要经过 Worker 的包装。这样才能够做到线程可以复用而无需重新创建线程。

同时 Executors 类里面有 newFixedThreadPool(),newCachedThreadPool() 等几个方法,实际上也是间接调用了 ThreadPoolExocutor ,不过是传的不同的构造参数。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值