ExecutorService 类

ExecutorService 类

ExecutorService 是 Java 中用于管理和执行线程的高级工具之一。它是 java.util.concurrent 包中的一部分,用于简化多线程编程和任务执行的复杂性。ExecutorService 提供了一个高层次的接口,用于调度和执行任务,以及管理线程池。

主要的功能和优点包括:

  1. 线程池管理ExecutorService 可以管理线程池,通过预先创建和维护一组线程来执行任务。这可以减少线程的创建和销毁开销,提高性能。

  2. 任务调度:它允许您提交任务,这些任务可以是 RunnableCallable 类型,然后由线程池中的线程来执行。

  3. 异步执行:任务可以并行执行,不必等待一个任务完成以后再执行下一个,从而提高应用程序的性能。

  4. 任务取消:可以取消已提交但尚未开始执行的任务。

  5. 异常处理ExecutorService 可以处理任务执行中的异常,确保应用程序不会因为一个任务的失败而崩溃。

  6. 可控性:您可以根据应用程序的需要配置线程池的大小,管理线程的生命周期,并监视线程池的执行。

以下是一些常见的 ExecutorService 的用法和场景:

  1. 多任务并行执行:当需要同时执行多个任务,而不想为每个任务手动创建线程时,ExecutorService 是一个很好的选择。例如,一个 Web 服务器可以使用 ExecutorService 来处理来自客户端的并发请求。

  2. 定时任务ScheduledExecutorServiceExecutorService 的一个子接口,它允许您调度任务在将来的某个时间点或以固定的时间间隔执行。这对于周期性任务非常有用,例如定时备份数据或执行定时的清理操作。

  3. 批量数据处理:当需要对大量数据进行并行处理时,可以使用 ExecutorService 来拆分任务,将其分配给多个线程以提高处理速度。例如,将大型数据集分成多个部分,每个部分由不同的线程处理。

示例:

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ExecutorServiceExample {
    public static void main(String[] args) {
        // 创建一个固定大小的线程池,最多同时执行两个任务
        ExecutorService executorService = Executors.newFixedThreadPool(2);

        // 提交两个任务给线程池执行
        executorService.submit(new MyTask("Task 1"));
        executorService.submit(new MyTask("Task 2"));

        // 关闭线程池
        executorService.shutdown();
    }
}

class MyTask implements Runnable {
    private String name;

    public MyTask(String name) {
        this.name = name;
    }

    @Override
    public void run() {
        System.out.println("Task " + name + " is executing in thread " + Thread.currentThread().getName());
    }
}

在上面的示例中,我们创建了一个固定大小的线程池,最多可以同时执行两个任务。然后,我们提交了两个任务给线程池执行。ExecutorService 管理了线程的生命周期和任务的执行,使得任务可以在不同的线程中并行执行。

ExecutorService 方法介绍

ExecutorService 是一个接口,它继承自 Executor 接口,并添加了一些用于任务管理和线程池控制的方法。具体的方法如下:

  1. void execute(Runnable command):

    • 用于提交一个 Runnable 任务以供执行。这是 Executor 接口中定义的方法,ExecutorService 接口继承了它。
  2. Future<?> submit(Runnable task):

    • 用于提交一个 Runnable 任务并返回一个 Future 对象,该对象可用于检查任务的执行状态或获取执行结果。
  3. <T> Future<T> submit(Callable<T> task):

    • 用于提交一个 Callable 任务并返回一个 Future 对象,用于获取任务的执行结果或检查任务的状态。
  4. Future<?> submit(Runnable task, T result):

    • 用于提交一个 Runnable 任务和一个结果,返回一个 Future 对象,该结果在任务完成后可用。
  5. List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks):

    • 用于提交一组 Callable 任务,并返回一个 Future 对象的列表,该列表包含每个任务的执行结果。
  6. List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit):

    • 类似于 invokeAll,但允许您指定一个超时时间,如果某些任务未在超时时间内完成,它们将被取消。
  7. <T> T invokeAny(Collection<? extends Callable<T>> tasks):

    • 用于提交一组 Callable 任务,返回首先成功完成的任务的执行结果,忽略其他任务。如果没有任务成功完成,它将抛出异常。
  8. <T> T invokeAny(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit):

    • 类似于 invokeAny,但允许您指定一个超时时间,如果在超时时间内没有任务成功完成,它将抛出异常。
  9. void shutdown():

    • 用于平稳地关闭 ExecutorService,不再接受新任务,但允许已提交的任务完成执行。
  10. List<Runnable> shutdownNow():

    • 尝试关闭 ExecutorService,并且停止正在执行的任务。返回一个列表,包含等待执行的任务。
  11. boolean isShutdown():

    • 用于检查 ExecutorService 是否已经关闭。
  12. boolean isTerminated():

    • 用于检查 ExecutorService 是否已经关闭并且所有任务已完成。
  13. boolean awaitTermination(long timeout, TimeUnit unit):

    • 用于等待 ExecutorService 关闭,直到超时或直到所有任务完成。

这些方法提供了对任务提交、控制线程池、管理任务状态以及关闭线程池的各种操作。根据不同的需求,您可以选择合适的方法来管理和执行任务。

Future<?> submit(Runnable task)

Future<?> submit(Runnable task) 方法用于提交一个 Runnable 任务给 ExecutorService 进行执行,但需要注意,Runnable 任务并不返回结果,因此 Future 对象的 get() 方法将始终返回 null。这是因为 Runnable 接口的 run() 方法没有返回值。

当使用 submit(Runnable task) 方法时,ExecutorService 会执行该任务,并且你可以通过 Future 对象来监控任务的执行状态,例如等待任务完成或取消任务。但不要期望从 Future 中获得任务的结果,因为 Runnable 任务没有返回值。

示例:

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

public class RunnableExample {
    public static void main(String[] args) {
        ExecutorService executorService = Executors.newSingleThreadExecutor();

        // 提交一个Runnable任务
        Future<?> future = executorService.submit(new MyRunnable());

        // 等待任务完成
        try {
            future.get(); // 这里将始终返回null
        } catch (Exception e) {
            e.printStackTrace();
        }

        // 关闭线程池
        executorService.shutdown();
    }
}

class MyRunnable implements Runnable {
    @Override
    public void run() {
        System.out.println("Runnable task is executing.");
    }
}

在上面的示例中,我们提交了一个 Runnable 任务给 ExecutorService,然后通过 future.get() 等待任务完成,但由于 Runnable 任务没有返回值,因此 get() 返回 null。这种情况下,Future 主要用于任务状态的监控,而不是获取结果。如果需要获取任务的结果,应该使用 submit(Callable<T> task) 方法,其中 Callable 任务可以返回一个值。

Future<?> submit(Runnable task)是否立即执行

Future<?> submit(Runnable task) 方法通常会立即提交 Runnable 任务给 ExecutorService 执行。然而,执行任务的确切时间取决于线程池中是否有可用的线程来执行任务。如果线程池中的线程都在执行其他任务,提交的任务可能会排队等待执行,直到有线程可用。

总结起来,submit(Runnable task) 方法的执行通常是立即提交任务,但任务的实际执行时间取决于线程池中的线程可用性和调度策略。如果有可用线程,任务将立即执行。如果没有可用线程,任务将排队等待执行,直到线程可用。

要确保任务立即执行,您可以使用 ExecutorService 的其他方法,例如 submit(Callable<T> task)execute(Runnable command),或者确保线程池中有足够的线程可用来执行任务。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

xwhking

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值