有些时候 jdk自带的cachedThreadPool fixedThreadPool等线程池完成不了我们业务的需求时 可以用ThreadPoolExecutorg构造自定义的线程池。
public class UseThreadPoolExecutor1 {
public static void main(String[] args) {
/**
* 在使用有界队列时,若有新的任务需要执行,如果线程池实际线程数小于corePoolSize,则优先创建线程,
* 若大于corePoolSize,则会将任务加入队列,
* 若队列已满,则在总线程数不大于maximumPoolSize的前提下,创建新的线程,
* 若线程数大于maximumPoolSize,则执行拒绝策略。或其他自定义方式。
*
*/
ThreadPoolExecutor pool = new ThreadPoolExecutor(
1, //coreSize
2, //MaxSize
60, //60
TimeUnit.SECONDS,
new ArrayBlockingQueue<Runnable>(3) //指定一种队列 (这里用大小为3的有界队列)
//new LinkedBlockingQueue<Runnable>()
, new MyRejected() // 这是实现了RejectedExecutionHandler接口的自定义处理类,可以处理线程满了并且队列满了的情况下新来任务(实际开发中可以记录在日志中 延后执行)
//, new DiscardOldestPolicy()
);
MyTask mt1 = new MyTask(1, "任务1");
MyTask mt2 = new MyTask(2, "任务2");
MyTask mt3 = new MyTask(3, "任务3");
MyTask mt4 = new MyTask(4, "任务4");
MyTask mt5 = new MyTask(5, "任务5");
MyTask mt6 = new MyTask(6, "任务6");
pool.execute(mt1);
pool.execute(mt2);
pool.execute(mt3);
pool.execute(mt4);
pool.execute(mt5);
pool.execute(mt6);
pool.shutdown();
}
}
这段代码会首先执行任务1,然后把2 3 4放入队列中,当任务5来到时,队列已满,这时候会判断是否达到了maxSize,如果还没到,就会新开一条线程给5,如果满了,就去执行MyRejected的自定义操作
所以上述代码执行顺序是
run taskId =1
run taskId =5
当前被拒绝任务为:6
run taskId =2
run taskId =3
run taskId =4
值得注意的是,如果使用的是无界队列,由于队列永远不会满,所以永远不会创建线程,线程会一直是coreSize,不会达到maxSize