大家好,又见面了,我是你们的朋友全栈君。
线程池(ThreadPool)是一种基于池化思想管理和使用线程的机制。它是将多个线程预先存储在一个“池子”内,当有任务出现时可以避免重新创建和销毁线程所带来性能开销,只需要从“池子”内取出相应的线程执行对应的任务即可。常见的运用池化思想的有:内存池、数据库连接池。使用线程池的优点如下:
假设银行正常可以同时给3个客户办理业务(绿色表示),最多可同时给5个用户办理业务(多余的用红色表示),等候区最多可以等待4个客户(用蓝色表示),小人表示客户。正常的营业厅处理业务流程如下图所示:
注:这个流程用于模拟线程池,和实际银行办理业务还是有点区别。
假设同时进来7个用户,办理业务效果如下:
4个等待区用户只有等前面的窗口办理完才能依次办理。
假设同时进来10个用户,办理业务效果如下:
第10个用户超出最大限度被拒绝办理业务,其余等待区用户只有等前面的窗口办理完才能依次办理,4和5号窗口超时后会重新进入空闲状态。
上面案例中的正常办理业务窗口数对应线程池中的核心线程数,最多办理业务窗口数对应线程池中的最大线程数,等候区对应线程池中的阻塞(等待)队列。线程池关键节点的执行流程如下:
线程池的执行流程如下图所示:
Java线程池一共有7种,按创建类分为两种:
一般使用Java提供了创建线程池的接口Executor(),推荐用子类ThreadPoolExecutor来创建线程池。这在阿里巴巴《Java开发手册》中有说明:
【强制】线程池不允许使用 Executors 去创建,而是通过 ThreadPoolExecutor 的方式,这样的处理方式让写的同学更加明确线程池的运行规则,规避资源耗尽的风险。 说明:Executors 返回的线程池对象的弊端如下: 1) FixedThreadPool 和 SingleThreadPool:允许的请求队列长度为 Integer.MAX_VALUE,可能会堆积大量的请求,从而导致 OOM。 2)CachedThreadPool:允许的创建线程数量为 Integer.MAX_VALUE,可能会创建大量的线程,从而导致 OOM。
该类参数最多的构造方法如下:
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler) {
// 省略相关代码
}
参数说明如下:
示例代码:
public class ThreadPoolTest {
public static void main(String[] args) {
ExecutorService executorService = new ThreadPoolExecutor(3,5,1L, TimeUnit.SECONDS,new ArrayBlockingQueue(4),Executors.defaultThreadFactory());
for(int i=0;i<7;i++){
executorService.execute(()->{
System.out.println(Thread.currentThread().getName()+" "+"--->办理业务");
});
}
executorService.shutdown();
}
}
运行结果:
pool-1-thread-2 --->办理业务
pool-1-thread-1 --->办理业务
pool-1-thread-3 --->办理业务
pool-1-thread-1 --->办理业务
pool-1-thread-2 --->办理业务
pool-1-thread-1 --->办理业务
pool-1-thread-3 --->办理业务
当for循环中的i<10时运行结果:
pool-1-thread-2 --->办理业务
pool-1-thread-4 --->办理业务
pool-1-thread-2 --->办理业务
pool-1-thread-3 --->办理业务
pool-1-thread-3 --->办理业务
pool-1-thread-1 --->办理业务
pool-1-thread-5 --->办理业务
pool-1-thread-2 --->办理业务
pool-1-thread-4 --->办理业务
Exception in thread "main" java.util.concurrent.RejectedExecutionException: Task com.test.ThreadPoolTest$$Lambda$1/1209271652@7a79be86 rejected from java.util.concurrent.ThreadPoolExecutor@880ec60[Running, pool size = 5, active threads = 0, queued tasks = 0, completed tasks = 9]
at java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:2047)
at java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:823)
at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1369)
at com.test.ThreadPoolTest.main(ThreadPoolTest.java:9)
可以发现只有9(最大+阻塞)个任务执行了,之后进来的任务会被拒绝。
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/156214.html原文链接:https://javaforall.cn