一起学JAVA之【基础篇】线程池 ThreadPoolExecutor使用详解
先来看一下线程池工作的流程图
概念
ThreadPoolExecutor类是用来自定义线程池的,他有4个构造方法:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EifmtEoj-1635843010813)(C:\Users\13782\AppData\Roaming\Typora\typora-user-images\image-20211102150650817.png)]
参数数量依次递增,参数分别表示:
corePoolSize(核心线程数):定义核心线程数,核心线程数必须小于等于最大线程数不然会报空指针
maximumPoolSize(最大线程数):定义最大线程数,最大线程必须大于等于核心线程数,最大线程-核心线程数=临时线程数(临时线程只有在线程阻塞任务队列满的时候才新建)
keepAliveTime(线程存活时长):临时线程数存活时长
unit(线程存活时长单位):临时线程数存活时长单位
workQueue(线程阻塞任务队列):当核心线程使用完后用来存放新增任务的数据结构
threadFactory(线程工厂):主要作用是用来捕获异常和设置线程名称
handler(拒绝策略):当线程池接收不了新的任务后执行的策略,默认AbortPolicy(丢弃任务并抛出RejectedExecutionException)
使用
自定义ThreadFactory
public class MyThreadFactory implements ThreadFactory {
private String prefix;
private AtomicInteger atomicInteger;
public MyThreadFactory(String prefix){
this.prefix = prefix;
//保证计数安全
atomicInteger = new AtomicInteger(1);
}
/**
* Constructs a new {@code Thread}. Implementations may also initialize
* priority, name, daemon status, {@code ThreadGroup}, etc.
*
* @param r a runnable to be executed by new thread instance
* @return constructed thread, or {@code null} if the request to
* create a thread is rejected
*/
@Override
public Thread newThread(Runnable r) {
return new Thread(r,prefix+atomicInteger.getAndIncrement());
}
}
public class MyThreadPool{
public static void main(String[] args){
//自定义线程工厂
ThreadFactory threadFactory = new MyThreadFactory("test-thread");
ExecutorService executorService = new ThreadPoolExecutor(1,1,60,TimeUnit.SECONDS,new LinkedBlockingQueue<>(),threadFactory);
executorService.execute(()->{System.out.println(1111);System.out.println(Thread.currentThread().getName());});
}
}
拒绝策略
Java内部自定义了4种拒绝策略:
1、ThreadPoolExecutor.AbortPolicy:丢弃任务并抛出RejectedExecutionException异常。
2、ThreadPoolExecutor.DiscardPolicy:丢弃任务,但是不抛出异常。
3、ThreadPoolExecutor.DiscardOldestPolicy:丢弃队列最前面的任务,然后重新提交被拒绝的任务
4、ThreadPoolExecutor.CallerRunsPolicy:由调用线程(提交任务的线程)处理该任务
5、我们也可以自己定义拒绝策略
public class MyRejectedExecutionHandler implements RejectedExecutionHandler {
/**
* Method that may be invoked by a {@link ThreadPoolExecutor} when
* {@link ThreadPoolExecutor#execute execute} cannot accept a
* task. This may occur when no more threads or queue slots are
* available because their bounds would be exceeded, or upon
* shutdown of the Executor.
*
* <p>In the absence of other alternatives, the method may throw
* an unchecked {@link RejectedExecutionException}, which will be
* propagated to the caller of {@code execute}.
*
* @param r the runnable task requested to be executed
* @param executor the executor attempting to execute this task
* @throws RejectedExecutionException if there is no remedy
*/
@Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) throws RejectedExecutionException {
//记录日志
//告警
}
}
总结
前面说了Executors这个工具类里面提供了4个创建线程池的方法,可能不太适用于我们的日常业务场景,通过上面的教程你就可以自己去根据你所需要的定义自己的线程池