深入了解Executor框架

100 阅读4分钟

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的使用方法。通过这些工具,开发者可以更加高效地管理线程和任务,提高并发编程的性能和可靠性。在实际开发中,根据具体需求选择合适的线程池和任务调度方式,可以大大提升应用程序的性能和可维护性。