Java中的线程池是一种预先创建一定数量的线程并维护它们以供需要时重用的机制。它的主要目的是减少线程的创建和销毁造成的开销,提高系统的性能和稳定性。线程池中的线程可分为两类:核心线程和非核心线程。核心线程在池中一直保持存活状态,而非核心线程则在池中空闲时会被销毁。
线程池的作用是管理和分配线程,避免因创建和销毁线程的开销而导致系统性能下降。线程池可以提高系统的并发性能,并允许更好地控制资源的使用。
在 Java 中,线程池通常使用 java.util.concurrent 包中的 ThreadPoolExecutor 类来实现。ThreadPoolExecutor 类包含了很多配置参数,例如线程池的大小、线程空闲时间、任务队列等等,可以通过设置这些参数来优化线程池的性能。
Java中线程池的构造函数和常见参数如下:
- ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler)
该构造函数创建一个ThreadPoolExecutor对象,参数说明如下:
- corePoolSize:线程池中核心线程的数量。当线程池空闲时,核心线程会一直保持存活状态,即使没有任务需要执行。默认情况下,核心线程数为 0。
- maximumPoolSize:线程池中最大线程数。当队列满了,非核心线程数达到最大值,新任务会被阻塞。默认情况下,最大线程数为 Integer.MAX_VALUE。
- keepAliveTime:线程空闲时间,超过这个时间的非核心线程会被销毁。默认情况下,非核心线程的空闲时间为 60 秒。
- unit:keepAliveTime 参数的时间单位。默认情况下,单位为秒。
- workQueue:任务队列。当任务提交给线程池时,如果线程池中的线程已经满了,则任务会被添加到任务队列中等待执行。常见的任务队列类型有以下几种:ArrayBlockingQueue、LinkedBlockingQueue、SynchronousQueue。
- threadFactory:用于创建新线程的工厂。可以通过自定义 ThreadFactory 实现自定义线程的创建和命名。
- handler:任务拒绝处理器。当线程池中的线程已经满了,并且任务队列也已经满了,此时新的任务被提交,就会触发拒绝处理机制。常见的拒绝处理器有以下几种:AbortPolicy、CallerRunsPolicy、DiscardOldestPolicy、DiscardPolicy。
- Executors 工具类提供的静态方法
Executors 类提供了一些静态方法来创建常用的线程池。例如,Executors.newFixedThreadPool() 方法可以创建一个固定大小的线程池,Executors.newCachedThreadPool() 方法可以创建一个根据需要自动调整大小的线程池。这些方法提供了一些默认值,通常适用于大多数情况。
常见的线程池参数如下:
- corePoolSize:通常设置为固定值,表示线程池中的核心线程数量。
- maximumPoolSize:通常设置为一个比较大的数值,表示线程池中最大线程数。
- keepAliveTime:通常设置为 0 或一个比较短的时间,表示非核心线程的空闲时间。
- unit:通常设置为 TimeUnit.SECONDS。
- workQueue:通常选择 LinkedBlockingQueue 或者 ArrayBlockingQueue,具体选择取决于任务的特性和线程池的大小。
- threadFactory:通常使用默认值即可。
- handler:通常选择 AbortPolicy,即任务队列已满时抛出异常。
以上是线程池常见的构造函数
使用线程池的步骤如下:
- 创建一个 ThreadPoolExecutor 对象,并指定线程池的大小、线程空闲时间、任务队列等参数。
- 创建一些任务,并将它们提交给线程池执行。
- 在任务执行完毕后,关闭线程池。
以下是一个示例代码,演示如何使用线程池:
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ThreadPoolDemo {
public static void main(String[] args) {
ExecutorService executor = Executors.newFixedThreadPool(5);
for (int i = 0; i < 10; i++) {
Runnable worker = new WorkerThread("" + i);
executor.execute(worker);
}
executor.shutdown();
while (!executor.isTerminated()) {
}
System.out.println("Finished all threads");
}
}
class WorkerThread implements Runnable {
private String message;
public WorkerThread(String s) {
this.message = s;
}
public void run() {
System.out.println(Thread.currentThread().getName() + " (Start) message = " + message);
processMessage();
System.out.println(Thread.currentThread().getName() + " (End)");
}
private void processMessage() {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
上述代码中,首先创建了一个 ThreadPoolExecutor 对象 executor,并指定线程池的大小为 5。然后,创建了 10 个 WorkerThread 对象,并将它们提交给 executor 执行。每个 WorkerThread 对象实现了 Runnable 接口,并实现了 run() 方法,在 run() 方法中打印出线程名称和消息,并调用 processMessage() 方法模拟执行任务的时间。最后,在所有任务执行完毕后,调用 executor.shutdown() 方法关闭线程池,并等待所有线程执行完毕后输出 “Finished all threads”。
开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 28 天,点击查看活动详情