为什么要是使用线程池?
在执行多线程任务的时候,如果每次都按照创建一个线程->运行线程->销毁线程,其实在创建和销毁阶段会消耗大量的时间,所以利用线程池可以让线程在运行完毕后不被销毁,继续复用提升系统性能。
线程池demo
我们可以利用 new ThreadPoolExecutor
创建一个简单的线程池
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue)
corePoolSize : 核心线程数
maximumPoolSize:最大线程数
keepAliveTime: 当线程数大于核心线程数的时候,空闲的线程等待任务的最长时间
unit: keepAliveTime 的时间单位
workQueue: 线程池的队列
创建完的线程池可以用 submit
提交线程到线程池中执行
线程池执行流程
-
一个线程池创建完毕后,如果当前线程数小于核心线程数,没新进来一个线程,线程池都会重新创建一个线程,直到达到核心线程数
-
当线程池中核心线程数已满的时候,再进来的线程将会被加入到队列中
如果队列是长度有限的,当线程数超多队列的长度后,将会再创建新的线程。 -
如果新创建的线程数量大于最大线程数,就会抛出异常,这时候可以指定对应的线程池拒绝策略来处理,这部分的内容文章后面会讲到。
下面我们使用一个简单的例子来说明线程池的使用:
public class ThrealPoolDemo {
public static void main(String[] args) throws InterruptedException {
LinkedBlockingDeque<Runnable> queue = new LinkedBlockingDeque<>();
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(5, 20, 10, TimeUnit.SECONDS,queue);
//创建20个线程到线程池中 执行
for(int i=0;i<20;i++){
int finalI = i;
threadPoolExecutor.submit(()->{
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(finalI +"---"+Thread.currentThread().getName()+" hello");
});
}
//关闭线程池
threadPoolExecutor.shutdown();
//检测线程池中的线程是否已经全部执行完毕
while (true){
Thread.sleep(500);
if(threadPoolExecutor.isTerminated()){
break;
}
}
System.out.println("线程池中所有线程执行完毕");
}
}