Java线程池

一、构造方法
public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory,
                              RejectedExecutionHandler handler)

参数解析:

int corePoolSize:在线程池中保持线程的数量,即使是空闲的
int maximumPoolSize:线程池中允许的线程的最大数量
long keepAliveTime:当线程数大于corePoolSize时,多余空闲线程终止前的最大等待时间
TimeUnit unit:keepAliveTime的时间单位
BlockingQueue<Runnable> workQueue:用于在任务执行前保持任务的队列
ThreadFactory threadFactory:创建新线程的线程工厂
RejectedExecutionHandler handler:线程限制和队列容量达到,执行程序被阻塞的拒绝策略
TimeUnit 取值:
TimeUnit.NANOSECONDS;       //纳秒 
TimeUnit.MICROSECONDS;      //微妙
TimeUnit.MILLISECONDS;      //毫秒
TimeUnit.SECONDS;           //秒
TimeUnit.MINUTES;           //分钟
TimeUnit.HOURS;             //小时 
TimeUnit.DAYS;               //天
workQueue 常见的阻塞队列:

ArrayBlockingQueue(有界队列)
LinkedBlockingQueue(无界队列)
SynchronousQueue

有界队列和无界队列的区别:
  • 有界队列
    有助于防止在使用有限最大PosiLosis时资源耗尽,但可以更难调整和控制。

初始的poolSize < corePoolSize,提交runnable任务,会直接做为new一个Thread的参数,立马执行 。
当提交的任务数超过了corePoolSize,会将当前的runable提交到一个block queue中。
有界队列满了之后,如果poolSize < maximumPoolsize时,会尝试new 一个Thread的进行救急处理,立马执行对应的runnable任务。
如果上面也无法处理了,就会走到第四步执行拒绝策略,防止资源耗尽。

  • 无界队列
    说LinkedBlockingQueue是无界队列是无预定义容量的时候,如果用无参构造函数初始化,默认的容量是Integer.MAX_VALUE

与有界队列相比,除非系统资源耗尽,否则无界的任务队列不存在任务入队失败的情况。当有新的任务到来,系统的线程数小于corePoolSize时,则新建线程执行任务。当达到corePoolSize后,就不会继续增加,若后续仍有新的任务加入,而没有空闲的线程资源,则任务直接进入队列等待。若任务创建和处理的速度差异很大,无界队列会保持快速增长,直到耗尽系统内存。

二、线程池种类

1、newSingleThreadExecutor

ExecutorService threadPool = Executors.newSingleThreadExecutor();

一个单线程的线程池。这个线程池只有一个线程在工作,也就是相当于单线程串行执行所有任务。如果这个唯一的线程因为异常结束,那么会有一个新的线程来替代它。此线程池保证所有任务的执行顺序按照任务的提交顺序执行。

2、newFixedThreadPool

ExecutorService threadPool = Executors.newFixedThreadPool(3);

创建固定大小的线程池。每次提交一个任务就创建一个线程,直到线程达到线程池的最大大小。线程池的大小一旦达到最大值就会保持不变,如果某个线程因为执行异常而结束,那么线程池会补充一个新线程。

3、newCachedThreadPool

ExecutorService threadPool = Executors.newCachedThreadPool();

创建一个可缓存的线程池。如果线程池的大小超过了处理任务所需要的线程,那么就会回收部分空闲的线程,当任务数增加时,此线程池又添加新线程来处理任务。

4、newScheduledThreadPool

ExecutorService pool = Executors.newScheduledThreadPool(10);

线程池支持定时以及周期性执行任务的需求。

5、newWorkStealingPool

ExecutorService threadPool = Executors.newWorkStealingPool();

newWorkStealingPool是jdk1.8才有的,会根据所需的并行层次来动态创建和关闭线程,通过使用多个队列减少竞争,底层用的ForkJoinPool来实现的。
ForkJoinPool的优势在于,可以充分利用多cpu,多核cpu的优势,把一个任务拆分成多个“小任务”,把多个“小任务”放到多个处理器核心上并行执行;当多个“小任务”执行完成之后,再将这些执行结果合并起来即可。

三、拒绝策略

当请求不断进来,而系统此时又处理不过来的时候,需要采取的策略是拒绝服务。RejectedExecutionHandler接口提供了拒绝任务处理的自定义方法的机会。在ThreadPoolExecutor中已经包含四种处理策略。
1、AbortPolicy
该策略会直接抛出异常,阻止系统正常工作。抛出RejectedExecutionException

2、CallerRunsPolicy
只要线程池未关闭,该策略直接在调用者线程中,运行当前的被丢弃的任务。

3、DiscardPolicy
该策略默默的丢弃无法处理的任务,不予任何处理。

4、DiscardOldestPolicy
该策略将丢弃最老的一个请求,也就是即将被执行的任务,并尝试再次提交当前任务。

四、线程池关闭

1、shutdownNow
对正在执行的任务全部发出interrupt(),停止执行,对还未开始执行的任务全部取消,并且返回还没开始的任务列表

2、shutdown
线程池将不再接受新的任务,但也不会去强制终止已经提交或者正在执行中的任务

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值