JDK自带线程池实例详解
线程池介绍
在应用程序开发中,使用线程是很常见的。当一个程序被执行时,它会生成一个主线程,这个主线程可以并行运行多个程序段。但如果程序中包含多个任务需要同时运行时,如果每个任务都创建自己的线程,这将会导致线程的大量创建和销毁,极度浪费资源。而线程池的出现解决了这个问题,它将多个任务合并在一起,让它们共享一个线程池中的线程完成任务。
线程池的实现
Java中提供了Executor框架来实现线程池。其中,Java.util.concurrent.Executor主要定义了线程的执行方式,通常我们可以通过ThreadPoolExecutor或ScheduledThreadPoolExecutor对其进行实现。
ThreadPoolExecutor
ThreadPoolExecutor实现了Executor框架的所有基本方法,并提供了一组可供我们调整的方法,以满足我们对线程池的各项要求。以下是ThreadPoolExecutor的构造函数:
public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, RejectedExecutionHandler handler) {
// ...
}
构造ThreadPoolExecutor需要传入以下6个参数:
- corePoolSize:核心线程池大小,当池中线程数少于corePoolSize时,虽然有新的任务提交,我们也会继续创建一个新的线程处理这个任务。
- maximumPoolSize:线程池最大线程数。
- keepAliveTime:空闲线程存活时间。
- unit:空闲线程存活时间单位。
- workQueue:用于暂存任务的阻塞队列,用于多余的任务排队等待执行。
- handler:饱和策略。
示例
下面是一个简单的示例,展示如何使用线程池:
import java.util.concurrent.*;
public class MyThreadPool {
public static void main(String[] args) {
// 创建线程池
ThreadPoolExecutor executor = new ThreadPoolExecutor(2, 4, 10, TimeUnit.SECONDS, new LinkedBlockingQueue<>());
// 提交任务
for(int i = 0; i < 10; i++) {
executor.execute(new Task(i));
}
// 关闭线程池
executor.shutdown();
}
}
class Task implements Runnable {
private int taskId;
public Task(int taskId) {
this.taskId = taskId;
}
@Override
public void run() {
System.out.println("Task " + taskId + " is running.");
}
}
在上述示例中,我们创建了一个ThreadPoolExecutor实例,并使用execute()方法提交了10个任务。由于我们创建了一个LinkedBlockingQueue队列,因此所有的任务被一个个地排队执行。最后,我们通过调用了executor.shutdown()来关闭线程池。
另外,我们可以通过重写RejectedExecutionHandler来自定义饱和策略,以下是一个示例:
import java.util.concurrent.*;
public class MyThreadPool {
public static void main(String[] args) {
// 创建线程池
ThreadPoolExecutor executor = new ThreadPoolExecutor(2, 4, 10, TimeUnit.SECONDS, new LinkedBlockingQueue<>(2),
(r, executor1) -> {
if (!executor1.isShutdown()) {
r.run();
}
});
// 提交任务
for(int i = 0; i < 10; i++) {
executor.submit(new Task(i));
}
// 关闭线程池
executor.shutdown();
}
}
class Task implements Runnable {
private int taskId;
public Task(int taskId) {
this.taskId = taskId;
}
@Override
public void run() {
System.out.println("Task " + taskId + " is running.");
}
}
在以上示例中,我们使用的是一个有界的队列(队列大小为2),当线程池没有空闲的线程,且队列也已经满时,我们将仍需要提交的任务直接运行在当前线程上。这是通过自定义RejectionExecutionHandler实现的。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:jdk自带线程池实例详解 - Python技术站