JDK自带线程池使用配置
ThreadPoolExecutor的完整构造方法的签名是:ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler)
.
corePoolSize - 池中所保存的线程数,包括空闲线程。
maximumPoolSize-池中允许的最大线程数。
keepAliveTime - 当线程数大于核心时,此为终止前多余的空闲线程等待新任务的最长时间。
unit - keepAliveTime 参数的时间单位。
workQueue - 执行前用于保持任务的队列。此队列仅保持由 execute方法提交的 Runnable任务。
threadFactory - 执行程序创建新线程时使用的工厂。
handler - 由于超出线程范围和队列容量而使执行被阻塞时所使用的处理程序。
ThreadPoolExecutor是Executors类的底层实现。
在JDK帮助文档中,有如此一段话:
“强烈建议程序员使用较为方便的Executors
工厂方法Executors.newCachedThreadPool()
(无界线程池,可以进行自动线程回收)、Executors.newFixedThreadPool(int)
(固定大小线程池)Executors.newSingleThreadExecutor()
(单个后台线程)
它们均为大多数使用场景预定义了设置。”
当一个任务将被添加到线程池中时:
如果当前线程数小于corePoolSize,即使有空闲线程,也会创建新的线程来处理新增任务;
如果当前线程数等于corePoolSize,如果缓冲队列未满,该任务被放入缓冲队列;
如果当前线程数大于corePoolSize,且冲队列已满,如果当前线程数小于maximumPoolSize, 就创建新的线程来处理新增任务;
如果当前线程数等于maximumPoolSize,且冲队列已满,将会使用handler所指定的策略来处理任务.
线程池处理任务的顺序是:
核心线程corePoolSize, 缓冲队列workQueue, 最大线程maximumPoolSize
当前线程数大于corePoolSize,线程池中的空闲线程在超过keepAliveTime, 会自动终止.线程池通过keepAliveTime来动态维护线程数.
unit的可选参数是java.util.concurrent.TimeUnit类中的
MICROSECONDS MILLISECONDS NANOSECONDS SECONDS
workQueue的参数有:
java.util.concurrent.ArrayBlockingQueue,该队列的长度有限制
java.util.concurrent.LinkedBlockingQueue,该队列的长度没有限制
建议使用ArrayBlockingQueue
handler的可选参数有:
ThreadPoolExecutor.AbortPolicy
抛出 RejectedExecutionException.
static class ThreadPoolExecutor.CallerRunsPolicy
重试添加当前任务,会重复调用execute();
static class ThreadPoolExecutor.DiscardOldestPolicy
放弃最旧的任务,然后重试 execute()方法;
static class ThreadPoolExecutor.DiscardPolicy
放弃当前任务.
示例代码:
mport java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class TestExecutor {
public static void main(String[] args) {
ThreadPoolExecutor executor = new ThreadPoolExecutor(
2, 5, 300, TimeUnit.MILLISECONDS,
new ArrayBlockingQueue<Runnable>(3),
new ThreadPoolExecutor.CallerRunsPolicy()
);
for (int i=1; i<15; i++){
executor.execute(new Task(i));
}
executor.shutdown();
}
}
class Task implements Runnable{
public Task(int num){
this.num = num;
}
public void run() {
System.out.println("任务名称="+"taskName"+num);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private int num;
}
ThreadPoolExecutor除了execute()方法外,还有afterExecute(),beforeExecute(),
另外,可以对ThreadPoolExecutor重写受保护的方法进行扩展.