虽然java提供了两种自动创建线程池的方式,但是线程使用起来情况比较复杂,提供的两种自动创建方式比较粗糙,故不推荐使用。
手动创建线程池
推荐使用ThreadPoolExecutor手动创建线程池的方式,该构造器有7个参数,参数介绍如下:
代码实现如下:
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class EssayTest {
public static void main(String[] args) {
// 1.创建线程池(手动创建)
/**
* ThreadPoolExecutor 参数列表
* 参数一:核心线程数
* 参数二:最大线程数
* 参数三:临时线程存活时长
* 参数四:临时线程存活时长单位
* 参数五:阻塞队列长度
* 参数六:创建线程工厂
* 参数七:拒绝策略
*/
ThreadPoolExecutor pool = new ThreadPoolExecutor(
3,
5,
6,
TimeUnit.SECONDS,
new ArrayBlockingQueue<>(5),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.AbortPolicy()
);
// 2.提交任务
for (int i = 0; i < 10; i++) {
pool.submit(new MyRunable(i));
}
// 3.销毁线程池
pool.shutdown();
}
}
class MyRunnable implements Runnable{
int num;
public MyRunnable(int num) {
this.num = num;
}
@Override
public void run() {
System.out.println("手动创建的线程池中的线程" + Thread.currentThread().getName() + " 正在处理任务:" + num);
}
}
四种拒接策略
拒绝策略是ThreadPoolExecutor构造器的最后一个参数,有以下四个备选:
AbortPolicy():丢弃任务,并抛弃异常
我这里将任务量设置为12,即12 > 5(最大线程数) + 5(阻塞队列长度),看下线程池是怎么执行拒绝策略的
DiscardPolicy():忽略任务,丢弃并不抛出异常(不推荐)
/**
* ThreadPoolExecutor 参数列表
* 参数一:核心线程数
* 参数二:最大线程数
* 参数三:临时线程存活时长
* 参数四:临时线程存活时长单位
* 参数五:阻塞队列长度
* 参数六:创建线程工厂
* 参数七:拒绝策略
*/
ThreadPoolExecutor pool = new ThreadPoolExecutor(
3,
5,
6,
TimeUnit.SECONDS,
new ArrayBlockingQueue<>(5),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.DiscardPolicy()
);
DiscardOldestPolicy():忽略排队时间最长的任务,并不抛出异常
/**
* ThreadPoolExecutor 参数列表
* 参数一:核心线程数
* 参数二:最大线程数
* 参数三:临时线程存活时长
* 参数四:临时线程存活时长单位
* 参数五:阻塞队列长度
* 参数六:创建线程工厂
* 参数七:拒绝策略
*/
ThreadPoolExecutor pool = new ThreadPoolExecutor(
3,
5,
6,
TimeUnit.SECONDS,
new ArrayBlockingQueue<>(5),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.DiscardOldestPolicy()
);
CallerRunsPolicy():绕过线程池,直接调用任务的run()方法(谁传过来的谁处理)
/**
* ThreadPoolExecutor 参数列表
* 参数一:核心线程数
* 参数二:最大线程数
* 参数三:临时线程存活时长
* 参数四:临时线程存活时长单位
* 参数五:阻塞队列长度
* 参数六:创建线程工厂
* 参数七:拒绝策略
*/
ThreadPoolExecutor pool = new ThreadPoolExecutor(
3,
5,
6,
TimeUnit.SECONDS,
new ArrayBlockingQueue<>(5),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.CallerRunsPolicy()
);