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 shutdownNow(); boolean isShutdown(); boolean isTerminated(); boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException; Future submit(Callable task); Future submit(Runnable task, T result); Future<?> submit(Runnable task); List<Future> invokeAll(Collection<? extends Callable> tasks) throws InterruptedException; List<Future> invokeAll(Collection<? extends Callable> tasks, long timeout, TimeUnit unit) throws InterruptedException; T invokeAny(Collection<? extends Callable> tasks) throws InterruptedException, ExecutionException; T invokeAny(Collection<? extends Callable> 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 workQueue); public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue workQueue, ThreadFactory threadFactory); public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue workQueue, RejectedExecutionHandler handler); public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue 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的使用方法。通过这些工具,开发者可以更加高效地管理线程和任务,提高并发编程的性能和可靠性。在实际开发中,根据具体需求选择合适的线程池和任务调度方式,可以大大提升应用程序的性能和可维护性。