线程池的工作主要是控制运行的线程的数量,处理过程中将任务放进队列,然后在线程创建后启动这些任务,如果线程数量超过了最大数量,超出数量的线程排队等候,等待其他线程执行完毕,在从队列中取出任务来执行。
主要特点为:线程复用,控制最大并发数,管理线程。
1. 线程池7大参数
- corePoolSize:线程池中的常驻核心线程数
- maximumPoolSize:线程池能够容纳同时执行的最大线程数,此值必须大于1
- keepAliveTime:多余的空闲线程存活时间。当前线程数量超过maximumPoolSize时,当空闲时间达到keepAliveTime时,多余空闲线程会被销毁直到只剩下corePoolSize个线程为止。
- unit:keepAliveTime的单位
- workQueue:任务队列,被提交但尚未执行的任务
- threadFactory:表示生成线程池中工作线程的线程工厂,用于创建线程,一般用默认的即可
- handler:决绝策略,表示当队列满了并且线程大于线程池的最大线程数(maximumPoolSize)
handler:决绝策略
- ThreadPoolExecutor.AbortPolicy:丢弃任务并抛出RejectedExecutionException异常。
ExecutorService threadPool = new ThreadPoolExecutor(2, 5, 1000, TimeUnit.SECONDS,
new LinkedBlockingQueue<>(3), Executors.defaultThreadFactory(),
new ThreadPoolExecutor.AbortPolicy());
try {
for (int i = 0; i < 8; i++) {
threadPool.execute(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(1000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " --> 办理业务");
}
});
}
} finally {
threadPool.shutdown();
}
- ThreadPoolExecutor.CallerRunsPolicy:“调用者运行”一种调节机制,该策略不会抛弃任务,也不会抛出异常,而是将某些任务回退到调用方。
ExecutorService threadPool = new ThreadPoolExecutor(2, 5, 1000, TimeUnit.SECONDS,
new LinkedBlockingQueue<>(3), Executors.defaultThreadFactory(), new ThreadPoolExecutor.CallerRunsPolicy());
try {
for (int i = 0; i < 10; i++) {
threadPool.execute(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(1000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " --> 办理业务");
}
});
}
} finally {
threadPool.shutdown();
}
回退给main线程调用
- ThreadPoolExecutor.DiscardPolicy:直接丢弃任务,不处理任何异常。如果允许任务丢弃,这个是最好的解决方式。
- ThreadPoolExecutor.DiscardOldestPolicy:丢弃队列等待最久的任务,然后把当前任务加入队列中尝试再次提交当前任务。
ExecutorService threadPool = new ThreadPoolExecutor(2, 5, 1000, TimeUnit.SECONDS,
new LinkedBlockingQueue<>(3), Executors.defaultThreadFactory(), new ThreadPoolExecutor.DiscardPolicy());
//ExecutorService threadPool = new ThreadPoolExecutor(2, 5, 1000, TimeUnit.SECONDS,
// new LinkedBlockingQueue<>(3), Executors.defaultThreadFactory(), new ThreadPoolExecutor.DiscardOldestPolicy());
try {
for (int i = 0; i < 10; i++) {
threadPool.execute(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(1000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " --> 办理业务");
}
});
}
} finally {
threadPool.shutdown();
}
DiscardPolicy和DiscardOldestPolicy丢弃任务,只执行8个线程。
2. 合理设置线程池参数
2.1 CPU密集型:
CPU密集型也叫计算密集型,指的是系统的硬盘、内存性能相对CPU要好很多,此时,系统运作大部分的状况是CPU Loading 100%,CPU要读/写I/O(硬盘/内存),I/O在很短的时间就可以完成,而CPU还有许多运算要处理,CPU Loading很高。
公式:cpu核数 + 1
2.2 IO密集型
IO密集型指的是系统的CPU性能相对硬盘、内存要好很多,此时,系统运作,大部分的状况是CPU在等I/O (硬盘/内存) 的读/写操作,此时CPU Loading并不高。
公式1:cpu核数 * 2
公式2:cpu核数 / (1 - 阻塞系数)
阻塞系数 一般是0.8-0.9之间