ThreadPoolExecutor构造方法参数说明
corePoolSize
核心线程数,默认情况下核心线程会一直存活,即使处于闲置状态也不会受存keepAliveTime限制。除非将allowCoreThreadTimeOut设置为true。
maximumPoolSize
线程池所能容纳的最大线程数。超过这个数的线程将被阻塞。当任务队列为没有设置大小的LinkedBlockingDeque时,这个值无效。
keepAliveTime
非核心线程的闲置超时时间,超过这个时间就会被回收。
unit
指定keepAliveTime的单位,如TimeUnit.SECONDS。当将allowCoreThreadTimeOut设置为true时对corePoolSize生效。
workQueue
线程池中的任务队列.
常用的有三种队列,SynchronousQueue,LinkedBlockingDeque,ArrayBlockingQueue。
如果你使用的LinkedBlockingQueue,也就是无界队列的话,没关系,继续添加任务到阻塞队列中等待执行,因为LinkedBlockingQueue可以近乎认为是一个无穷大的队列,可以无限存放任务;如果你使用的是有界队列比方说ArrayBlockingQueue的话,任务首先会被添加到ArrayBlockingQueue中,ArrayBlockingQueue满了,则会使用 拒绝策略 RejectedExecutionHandler处理满了的任务,默认是AbortPolicy。
threadFactory
线程工厂,提供创建新线程的功能。ThreadFactory是一个接口,只有一个方法
RejectedExecutionHandler
RejectedExecutionHandler
也是一个接口,只有一个方法.当线程池中的资源已经全部使用,添加新线程被拒绝时,会调用RejectedExecutionHandler的rejectedExecution方法。
下面都假设任务队列没有大小限制:
如果线程数量<=核心线程数量,那么直接启动一个核心线程来执行任务,不会放入队列中。
如果线程数量>核心线程数,但<=最大线程数,并且任务队列是LinkedBlockingDeque的时候,超过核心线程数量的任务会放在任务队列中排队。
如果线程数量>核心线程数,但<=最大线程数,并且任务队列是SynchronousQueue的时候,线程池会创建新线程执行任务,这些任务也不会被放在任务队列中。这些线程属于非核心线程,在任务完成后,闲置时间达到了超时时间就会被清除。
如果线程数量>核心线程数,并且>最大线程数,当任务队列是LinkedBlockingDeque,会将超过核心线程的任务放在任务队列中排队。也就是当任务队列是LinkedBlockingDeque并且没有大小限制时,线程池的最大线程数设置是无效的,他的线程数最多不会超过核心线程数。
如果线程数量>核心线程数,并且>最大线程数,当任务队列是SynchronousQueue的时候,会因为线程池拒绝添加任务而抛出异常。
任务队列大小有限时
当LinkedBlockingDeque塞满时,新增的任务会直接创建新线程来执行,当创建的线程数量超过最大线程数量时会抛异常。
SynchronousQueue没有数量限制。因为他根本不保持这些任务,而是直接交给线程池去执行。当任务数量超过最大线程数时会直接抛异常。因为SynchronousQueue各奔不保存任务,收到一个任务就去创建新线程
---------------------
1.4 handler
handler 是线程池拒绝处理任务的方式,主要有四种类型:
ThreadPoolExecutor.AbortPolicy()(系统默认):抛出java.util.concurrent.RejectedExecutionException异常
ThreadPoolExecutor.CallerRunsPolicy():当抛出RejectedExecutionException异常时,会调用rejectedExecution方法
ThreadPoolExecutor.DiscardOldestPolicy():抛弃旧的任务
ThreadPoolExecutor.DiscardPolicy():抛弃当前的任务
java.util.concurrent.ScheduledExecutorService
接口继承了ExecutorService,它的最主要的功能就是可以对其中的任务进行调度,比如延迟执行、定时执行等等。
提供了四个方法,下面我们就分别介绍:
1. schedule (Runnable task, long delay, TimeUnit timeunit)//这个方法的意思是在指定延迟之后运行task。这个方法有个问题,就是没有办法获知task的执行结果
2. schedule (Callable task, long delay, TimeUnit timeunit)//在指定延迟之后运行task,不过它接收的是一个Callable实例,此方法会返回一个ScheduleFuture对象,通过ScheduleFuture我们可以取消一个未执行的task,也可以获得这个task的执行结
3. scheduleAtFixedRate (Runnable, long initialDelay, long period, TimeUnit timeunit)//周期性的调度task执行。task第一次执行的延迟根据initialDelay
参数确定,以后每一次执行都间隔period
时长。
如果task的执行时间大于定义的period,那么下一个线程将在当前线程完成之后再执行。整个调度保证不会出现一个以上任务同时执行
4. scheduleWithFixedDelay (Runnable, long initialDelay, long period, TimeUnit timeunit)//在scheduleAtFixedRate中,period指的两个任务开始执行的时间间隔,也就是当前任务的开始执行时间和下个任务的开始执行时间之间的间隔。而在scheduleWithFixedDelay中,period指的当前任务的结束执行时间到下个任务的开始执行时间