Java线程池可以有效控制线程的数量,提高程序的性能和资源利用率。但是在使用线程池的过程中,我们需要考虑线程池中多余的线程是如何回收的。下面我将从线程池的工作原理、线程池中的线程回收机制两个方面讲解这个问题。
线程池的工作原理
线程池在创建时会预先分配一定数量的线程。当用户提交任务时,线程池就会将任务分配给其中的一个空闲线程执行。如果线程池中没有空闲的线程,那么任务就会进入任务队列等待执行。当一个线程完成了任务后,它会从任务队列中取出下一个任务执行。
线程池中的线程回收机制
线程池中的线程回收机制主要体现在两个方面:空闲线程的回收和超时线程的回收。
1. 空闲线程的回收
线程池中的线程通常分为核心线程和非核心线程。当线程池中的线程数大于核心线程数时,非核心线程就成为了多余的线程。这些多余的线程默认情况下会在经过一定时间后被回收。具体实现方式取决于线程池的实现,可以有如下两种方式:
-
Java自带的线程池实现类ThreadPoolExecutor采用了一种maxIdleTime为60秒的回收策略。当有线程处于空闲状态超过60秒时,就会被回收。
-
HikariCP线程池的实现类HikariThreadPoolExecutor采用了一种新的回收策略,称之为熔断策略。当空闲线程存活时间超过maxLifetime时,会进入熔断状态。在熔断状态下,线程的空闲时间不会被计算。只有当线程池中的线程小于核心线程数时,才会回收处于熔断状态的线程。
2. 超时线程的回收
超时线程是指线程执行任务时超过给定时间限制的线程。具体实现方式也有如下的两种:
-
在ThreadPoolExecutor中,可以通过设置allowCoreThreadTimeOut参数为true来启动超时线程的回收机制。当一个线程处于空闲状态超过keepAliveTime时间,并且线程池中的线程数量大于corePoolSize,那么这个线程就会被回收。
-
在HikariCP线程池中,超时线程的回收机制是通过设置threadTimeout = 30秒实现的。当一个线程执行任务的时间超过30秒时,会被认为超时,线程就会被回收。
示例说明
下面通过两个简单的示例来说明Java线程池中多余的线程是如何回收的。
public class ThreadPoolTest {
public static void main(String[] args) {
ExecutorService executorService = Executors.newFixedThreadPool(5);
for (int i = 0; i < 10; i++) {
executorService.execute(() -> {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "执行任务完毕");
});
}
executorService.shutdown();
}
}
上面的示例中,创建了一个具有5个线程的线程池,然后提交了10个任务给线程池执行。由于线程池中的核心线程数为5,非核心线程数为5,因此只有5个线程可以同时执行任务,剩下的5个任务会进入任务队列等待执行。当一个线程完成任务后,它会继续等待下一个任务执行。如果线程空闲时间超过60秒,那么就会被回收。
public class ThreadPoolTest {
public static void main(String[] args) {
ExecutorService executorService = new ThreadPoolExecutor(5, 10,
60, TimeUnit.SECONDS,
new LinkedBlockingQueue<>(20),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.AbortPolicy());
for (int i = 0; i < 30; i++) {
executorService.execute(() -> {
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "执行任务完毕");
});
}
executorService.shutdown();
}
}
上面的示例中,创建了一个具有5个核心线程和10个最大线程的线程池,超时时间为60秒。提交了30个任务给线程池执行。由于任务执行时间为10秒,因此线程池中只有5个线程可以同时执行任务,剩下的25个任务会进入任务队列等待执行。当线程空闲时间超过60秒时,多余的线程就会被回收。如果在任务执行时超过60秒,那么线程也会被回收。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java线程池中多余的线程是如何回收的 - Python技术站