目录
3.2 Executor、ExecutorService和ThreadPoolExecutor
3.1 引言
Executor框架的重要性
在Java并发编程中,直接使用Thread
类和Runnable
接口来管理线程显得过于底层和繁琐。为了更好地管理线程池和任务,Java提供了Executor
框架。该框架简化了并发编程,使得任务的提交和线程的管理更加灵活和高效。通过Executor
框架,开发者可以专注于任务本身,而不需要处理复杂的线程生命周期管理。此外,Executor
框架提供了线程池、定时任务调度等高级功能,大大提升了并发编程的便捷性和性能。
本文的内容结构
本文将详细介绍Java中Executor
框架的使用,主要内容包括:
Executor
、ExecutorService
和ThreadPoolExecutor
- 创建和管理线程池的示例
ScheduledExecutorService
的使用方法
3.2 Executor、ExecutorService和ThreadPoolExecutor
各类Executor的介绍和使用方法
Executor是一个顶级接口,定义了任务提交的基础方法:
public interface Executor {
void execute(Runnable command);
}
ExecutorService扩展了Executor
接口,提供了管理终止和生成Future
以跟踪一个或多个异步任务执行的功能:
public interface ExecutorService extends Executor {
void shutdown();
List<Runnable> shutdownNow();
boolean isShutdown();
boolean isTerminated();
boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException;
<T> Future<T> submit(Callable<T> task);
<T> Future<T> submit(Runnable task, T result);
Future<?> submit(Runnable task);
<T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks) throws InterruptedException;
<T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit) throws InterruptedException;
<T> T invokeAny(Collection<? extends Callable<T>> tasks) throws InterruptedException, ExecutionException;
<T> T invokeAny(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit) throws InterruptedException, ExecutionException;
}
ThreadPoolExecutor是ExecutorService
的实现类,提供了灵活的线程池功能:
public class ThreadPoolExecutor extends AbstractExecutorService {
public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue);
public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory);
public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, RejectedExecutionHandler handler);
public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler);
}
创建和管理线程池的示例
使用FixedThreadPool
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class FixedThreadPoolDemo {
public static void main(String[] args) {
ExecutorService executor = Executors.newFixedThreadPool(5); // 创建包含5个线程的固定线程池
for (int i = 0; i < 10; i++) {
Runnable task = new Task(i);
executor.execute(task);
}
executor.shutdown(); // 关闭线程池
}
}
class Task implements Runnable {
private final int taskId;
public Task(int taskId) {
this.taskId = taskId;
}
@Override
public void run() {
System.out.println("Task " + taskId + " is running on thread " + Thread.currentThread().getName());
}
}
使用CachedThreadPool
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class CachedThreadPoolDemo {
public static void main(String[] args) {
ExecutorService executor = Executors.newCachedThreadPool(); // 创建一个根据需要创建新线程的线程池
for (int i = 0; i < 10; i++) {
Runnable task = new Task(i);
executor.execute(task);
}
executor.shutdown(); // 关闭线程池
}
}
class Task implements Runnable {
private final int taskId;
public Task(int taskId) {
this.taskId = taskId;
}
@Override
public void run() {
System.out.println("Task " + taskId + " is running on thread " + Thread.currentThread().getName());
}
}
使用ScheduledThreadPool
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class ScheduledThreadPoolDemo {
public static void main(String[] args) {
ScheduledExecutorService executor = Executors.newScheduledThreadPool(5); // 创建包含5个线程的调度线程池
for (int i = 0; i < 5; i++) {
Runnable task = new Task(i);
executor.schedule(task, 2, TimeUnit.SECONDS); // 延迟2秒执行任务
}
executor.shutdown(); // 关闭线程池
}
}
class Task implements Runnable {
private final int taskId;
public Task(int taskId) {
this.taskId = taskId;
}
@Override
public void run() {
System.out.println("Task " + taskId + " is running on thread " + Thread.currentThread().getName());
}
}
3.3 ScheduledExecutorService
定时任务的调度和管理
ScheduledExecutorService
接口扩展了ExecutorService
,提供了定时任务的调度功能。可以使用它来调度一次性任务或周期性任务。
创建定时任务
可以使用schedule
方法调度一次性任务:
ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
Runnable task = () -> System.out.println("Scheduling: " + System.nanoTime());
executor.schedule(task, 3, TimeUnit.SECONDS);
executor.shutdown();
在这个示例中,任务将在3秒后执行。
创建周期性任务
可以使用scheduleAtFixedRate
方法调度周期性任务:
ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
Runnable task = () -> System.out.println("Scheduling: " + System.nanoTime());
executor.scheduleAtFixedRate(task, 0, 1, TimeUnit.SECONDS); // 每秒执行一次任务
可以使用scheduleWithFixedDelay
方法调度具有固定延迟的周期性任务:
ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
Runnable task = () -> System.out.println("Scheduling: " + System.nanoTime());
executor.scheduleWithFixedDelay(task, 0, 1, TimeUnit.SECONDS); // 每次任务执行完毕后等待1秒再执行
示例代码和应用场景
示例代码
以下是一个使用ScheduledExecutorService
调度定时任务的完整示例:
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class ScheduledExecutorServiceDemo {
public static void main(String[] args) {
ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
Runnable task = () -> System.out.println("Scheduling: " + System.nanoTime());
// 调度一次性任务,延迟3秒执行
executor.schedule(task, 3, TimeUnit.SECONDS);
// 调度周期性任务,每秒执行一次
executor.scheduleAtFixedRate(task, 0, 1, TimeUnit.SECONDS);
// 调度具有固定延迟的周期性任务,每次任务执行完毕后等待1秒再执行
executor.scheduleWithFixedDelay(task, 0, 1, TimeUnit.SECONDS);
// 一段时间后关闭executor,避免程序无限运行
executor.schedule(() -> {
executor.shutdown();
System.out.println("Executor shut down.");
}, 10, TimeUnit.SECONDS);
}
}
应用场景
ScheduledExecutorService
常用于以下场景:
- 定时任务:如定期备份数据、定期生成报表等。
- 周期性任务:如心跳检测、定时清理缓存等。
- 延迟任务:如延迟执行任务、任务重试等。
结论
本文深入介绍了Java中的Executor
框架,重点介绍了Executor
、ExecutorService
、ThreadPoolExecutor
和ScheduledExecutorService
的使用方法。在实际开发中,根据具体需求选择合适的线程池和任务调度方式,可以大大提升应用程序的性能和可维护性。希望本文对你有所帮助,敬请期待专栏的下一篇文章。