Java ThreadPoolExecutor 并发调用实例详解
Java中的线程池可以提高应用程序的性能和可伸缩性。ThreadPoolExecutor是一个实现了ExecutorService接口的线程池类。通过ThreadPoolExecutor的配置,可以定制线程池的大小、任务队列大小、线程空闲时间等参数,以适应不同的应用场景。
ThreadPoolExecutor的构造方法
public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler)
- corePoolSize:指定线程池的基本大小,即对外提供线程的数量。
- maximumPoolSize:指定线程池中允许的最大线程数。
- keepAliveTime:指定线程池中线程保持空闲状态的时间。
- unit:指定keepAliveTime参数的时间单位。
- workQueue:指定一个阻塞队列,用于存储等待执行的任务。
- threadFactory:指定创建线程的工厂类。
- handler:指定当待执行的任务超出线程池最大容量时的处理策略。
ThreadPoolExecutor的状态
ThreadPoolExecutor一共拥有5种状态:
- RUNNING:线程池在正常运行状态下接收新任务,并且可以处理阻塞队列中的任务。
- SHUTDOWN:线程池不再接收新任务,但是可以处理阻塞队列中的任务。
- STOP:线程池不再接收新任务,并且不再处理阻塞队列中的任务,正在执行的任务也可以被中断。
- TIDYING:当任务队列和线程池都为空时,线程池到达TIDYING状态,当完成状态转换后会调用terminated()方法。
- TERMINATED:terminated()方法执行完毕后,线程池到达TERMINATED状态。
例子1:自定义拒绝策略
public static void main(String[] args) {
ThreadPoolExecutor executor = new ThreadPoolExecutor(2, 4, 1, TimeUnit.SECONDS,
new ArrayBlockingQueue<>(4), Executors.defaultThreadFactory(), new MyRejectedExecutionHandler());
for (int i = 1; i <= 15; i++) {
executor.execute(() -> {
System.out.println(Thread.currentThread().getName() + " 执行!");
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
});
}
}
这个例子中,创建了一个大小为2-4的线程池,使用了ArrayBlockingQueue作为任务队列。在创建线程池时我们传入了自定义的MyRejectedExecutionHandler,它是RejectedExecutionHandler接口的实现类,用于处理线程池在满负荷运作时拒绝新任务的情况。
public class MyRejectedExecutionHandler implements RejectedExecutionHandler {
@Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
System.out.println("线程池已满,拒绝执行 " + r.toString());
}
}
这个拒绝策略很简单,只是在控制台输出一行日志。在主函数中,我们提交了15个任务到线程池,虽然线程池只能处理4个任务,但是我们不会收到RejectedExecutionException异常,因为我们设置了自定义的拒绝策略。
例子2:定时执行任务
public static void main(String[] args) throws InterruptedException {
ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(1);
executor.scheduleAtFixedRate(() -> {
System.out.println(Thread.currentThread().getName() + " 执行!");
}, 0, 1, TimeUnit.SECONDS);
TimeUnit.SECONDS.sleep(5);
executor.shutdown();
}
在这个例子中,我们使用了ScheduledThreadPoolExecutor来创建定时任务。在构造函数中,我们传入一个1,表示只有一个线程在执行任务,并且使用scheduleAtFixedRate方法设置任务的执行周期以及执行初始延迟时间。在这里,任务会每隔1秒钟执行1次。
在主函数中,我们使用TimeUnit.SECONDS.sleep(5)让程序等待5秒钟,然后使用executor.shutdown()关闭线程池。
通过这两个例子,我们可以看到使用Java线程池能够极大的提高代码的可伸缩性和性能,并且灵活定制线程池的各种参数,可以满足各种复杂的业务场景。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:java ThreadPoolExecutor 并发调用实例详解 - Python技术站