目录
一、Java线程池介绍
二、几种常见的线程池
2.1 FixedThreadPool
2.2 CachedThreadPool
2.3 ScheduledThreadPool
2.4 SingleThreadPool
2.5 WorkStealingPool
三、线程池的运用场景
3.1 FixedThreadPool(固定大小线程池)
3.2 CachedThreadPool(缓存线程池)
3.3 ScheduledThreadPool(定时任务线程池)
3.4 SingleThreadPool(单线程线程池)
3.5 WorkStealingPool(工作窃取线程池)
四、线程池创建时的核心参数
4.1 corePoolSize(核心线程数)
4.2 maximumPoolSize(最大线程数)
4.3 keepAliveTime(线程空闲时间)
4.4 unit(线程空闲时间单位)
4.5 workQueue(工作队列)
4.6 threadFactory(线程工厂)
4.7 handler(拒绝策略)
在Java中,线程池是一种管理和复用线程的机制,用于提高多线程应用程序的性能和资源利用率。线程池在执行任务时,可以避免频繁地创建和销毁线程,从而减少了系统开销,并且能够更有效地利用系统资源。Java中线程池的主要作用包括以下方面:
① 线程的复用:线程池会预先创建一定数量的线程,并将它们保存在池中。当有任务需要执行时,线程池会分配一个空闲的线程来执行任务,执行完毕后线程不会销毁,而是重新放入线程池中,等待下一个任务的到来。这种线程的复用避免了频繁地创建和销毁线程,提高了线程的利用率。
② 资源管理:线程池可以限制并发线程的数量,避免系统因为线程过多而导致资源耗尽或性能下降的问题。通过配置线程池的核心参数,可以控制线程数量的上限、空闲线程的存活时间等,从而更好地管理系统资源。
③ 任务调度:线程池可以用于执行各种类型的任务,包括周期性任务、延迟任务、定时任务等。通过使用不同类型的线程池和调度策略,可以灵活地调度任务的执行时间和执行方式,满足不同场景下的需求。
Java中线程池的实现主要依赖于java.util.concurrent包下的Executor接口及其子接口ExecutorService,以及ThreadPoolExecutor等具体实现类。开发人员可以通过这些接口和类来创建和管理线程池,并通过配置不同的参数来满足不同的需求。
FixedThreadPool(固定大小线程池):该线程池会一直保持在核心线程数的数量不变,即使有空闲线程。当有新任务提交时,如果所有核心线程都在执行任务,新任务会被放入队列中等待。这种线程池适用于负载较重的服务器。
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class FixedThreadPoolExample {
public static void main(String[] args) {
// 创建一个固定大小为3的线程池
ExecutorService executor = Executors.newFixedThreadPool(3);
for (int i = 0; i < 10; i++) {
final int taskId = i;
executor.execute(() -> {
System.out.println("Task " + taskId + " is executing by " + Thread.currentThread().getName());
try {
Thread.sleep(2000); // 模拟任务执行时间
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Task " + taskId + " completed.");
});
}
executor.shutdown();
}
}
CachedThreadPool(缓存线程池):该线程池会根据需要自动创建新线程,但在一定的时间范围内会重用之前创建的线程。如果线程长时间空闲,它会被回收,从而减少系统资源的占用。适用于执行大量短期异步任务的情况。
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class CachedThreadPoolExample {
public static void main(String[] args) {
// 创建一个可缓存线程池
ExecutorService executor = Executors.newCachedThreadPool();
for (int i = 0; i < 10; i++) {
final int taskId = i;
executor.execute(() -> {
System.out.println("Task " + taskId + " is executing by " + Thread.currentThread().getName());
try {
Thread.sleep(2000); // 模拟任务执行时间
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Task " + taskId + " completed.");
});
}
executor.shutdown();
}
}
ScheduledThreadPool(定时任务线程池):该线程池可用于执行定时任务和周期性任务。它可以指定核心线程数,当任务执行时间超过线程池核心线程数时,会创建新线程来处理。
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class ScheduledThreadPoolExample {
public static void main(String[] args) {
// 创建一个定时任务线程池
ScheduledExecutorService executor = Executors.newScheduledThreadPool(3);
executor.scheduleAtFixedRate(() -> {
System.out.println("Task executing by " + Thread.currentThread().getName());
}, 0, 3, TimeUnit.SECONDS); // 初始延迟0秒,每3秒执行一次任务
}
}
SingleThreadPool(单线程线程池):该线程池只有一个核心线程,所有任务按照指定顺序执行,即保证了任务的顺序性。如果该线程异常结束,会重新创建一个新的线程来替代。适用于需要顺序执行任务且保证线程安全的情况。
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class SingleThreadPoolExample {
public static void main(String[] args) {
// 创建一个单线程线程池
ExecutorService executor = Executors.newSingleThreadExecutor();
for (int i = 0; i < 5; i++) {
final int taskId = i;
executor.execute(() -> {
System.out.println("Task " + taskId + " is executing by " + Thread.currentThread().getName());
try {
Thread.sleep(2000); // 模拟任务执行时间
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Task " + taskId + " completed.");
});
}
executor.shutdown();
}
}
WorkStealingPool(工作窃取线程池):Java 8引入了这种新型线程池,它的核心思想是让空闲的线程从其他任务队列中窃取任务来执行,以提高线程利用率。这种线程池适用于处理大量耗时较长的任务。
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
public class WorkStealingPoolExample {
public static void main(String[] args) throws InterruptedException {
// 获取当前系统的处理器数量作为线程池大小
int processors = Runtime.getRuntime().availableProcessors();
// 创建工作窃取线程池
ExecutorService executor = Executors.newWorkStealingPool(processors);
for (int i = 0; i < 10; i++) {
final int taskId = i;
executor.execute(() -> {
System.out.println("Task " + taskId + " is executing by " + Thread.currentThread().getName());
try {
Thread.sleep(2000); // 模拟任务执行时间
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Task " + taskId + " completed.");
});
}
executor.awaitTermination(10, TimeUnit.SECONDS);
executor.shutdown();
}
}