线程池的工作就是控制运行线程的数量,处理过程中将任务放入队列,然后在线程创建后启动这些任务,如果线程数量超过了最大数量,超出数量的线程排队等候,等其他线程执行完毕,再从队列中取出任务来执行。
翻译:就是一开始就创建一定数量的线程。来一个用一个,用完了不销毁,返还到池子里等着被下一次调用。 如果需要的线程大于了我线程池准备好的线程,那么久等待,空出来一个,用一个。
线程池主要特点:
public static void main(String[] args) {
ExecutorService threadPool = Executors.newFixedThreadPool(5);
try {
for(int i = 1 ; i <= 10;i++){
threadPool.execute(()->{
System.out.println(Thread.currentThread().getName()+"开始工作");
});
}
}catch (Exception e){
e.printStackTrace();
}finally {
threadPool.shutdown();
}
}
结果:
可以看到,线程最大就跑到5,说明之前==newFixedThreadPool(5)==参数有效。而有部分线程多次出现,这里就说明,某个线程结束自己的工作之后,马上回到了线程池,接受并执行了下一个业务请求!
试想一下上面的代码,在某些超大项目中,如果我们把线程数量写死。一旦请求多了起来,来了1000个请求希望用线程池中的线程,而我们仅仅只有5个备用的线程。那程序还不得被卡死啊?
所以出现了一种创建线程的方法,让线程池遇强则强,可扩容!
ExecutorService threadPool = Executors.newCachedThreadPool();
结果:
多次测试结果都不同,线程数根据程序访问强度而或多或少。
1. 固定线程数newFixedThreadPool(5)原理:
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
最终返回一个ThreadPoolExecutor对象,是不是很眼熟??没错就是上面架构图中线程池的核心实现类!
2. 可扩容线程数newCachedThreadPool()原理:
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}
同样是返回一个ThreadPoolExecutor对象,只是创建对象所传的构造方法参数不同。 而参数的数量都是一样的 5个!
public ThreadPoolExecutor(int corePoolSize, 1
int maximumPoolSize, 2
long keepAliveTime, 3
TimeUnit unit, 4
BlockingQueue<Runnable> workQueue, 5
ThreadFactory threadFactory, 6
RejectedExecutionHandler handler 7
) {
}
线程池使用流程:
ExecutorService threadPool = new ThreadPoolExecutor(
2,
5,
2L,
TimeUnit.SECONDS,
new LinkedBlockingDeque<>(3),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.AbortPolicy()
);
好了 基本已经讲完,欢迎大家评论区指出不足,一起学习进步!
大家看完了点个赞,码字不容易啊。。。