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. Future submit(Callable task):

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

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

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

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

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

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

    • 用于平稳地关闭 ExecutorService,不再接受新任务,但允许已提交的任务完成执行。
  10. List 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 task) 方法,其中 Callable 任务可以返回一个值。

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

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

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

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

你可能感兴趣的:(Java,java,开发语言)