在这篇文章中,我们将通过实例学习ExecutorService接口的重要方法。
ExecutorService
接口为execute
补充了一个类似的、但更通用的submit
方法。和execute一样,submit接受Runnable对象,但也接受Callable
对象,它允许任务返回一个值。submit方法返回一个Future对象,用于检索Callable
返回值,并管理Callable
和Runnable任务的状态。
ExecutorService
还提供了提交Callable
对象的大型集合的方法。最后,ExecutorService
提供了许多方法来管理执行器的关闭。为了支持立即关机,任务应该正确处理中断。
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, TimeoutException;
}
让我们在这里列出所有的方法与描述。
boolean awaitTermination(long timeout, TimeUnit unit)
- 阻止所有任务在关闭请求后完成执行,或超时发生,或当前线程被中断,以先发生者为准。List<Future> invokeAll(Collection<? extends Callable> tasks)
- 执行给定的任务,当所有任务完成后,返回一个持有其状态和结果的Futures列表。List<Future> invokeAll(Collection<? extends Callable> tasks, long timeout, TimeUnit unit)
- 执行给定的任务,当所有任务完成或超时结束时(以先发生者为准),返回保持其状态和结果的期货列表。T invokeAny(Collection<? extends Callable> tasks)
- 执行给定的任务,如果有任务成功完成(即没有抛出异常),则返回其中的结果。T invokeAny(Collection<? extends Callable> tasks, long timeout, TimeUnit unit) -
执行给定的任务,如果有任务在给定的超时时间内完成,则返回已经成功完成(即没有抛出异常)的结果。boolean isShutdown()
- 如果这个执行器已经被关闭,则返回true。boolean isTerminated() -
如果所有的任务在关闭后都已完成,则返回true。void shutdown()
- 启动有序的关闭,在此过程中,先前提交的任务被执行,但不接受新任务。List shutdownNow()
- 试图停止所有正在执行的任务,停止处理等待中的任务,并返回一个等待执行的任务的列表。Future submit(Callable task)
- 提交一个返回值的任务供执行,并返回一个代表该任务的等待结果的Future。Future<?> submit(Runnable task)
- 提交一个Runnable任务供执行,并返回一个代表该任务的Future。Future submit(Runnable task, T result)
- 提交一个可运行的任务供执行,并返回一个代表该任务的Future。让我们通过例子来演示重要的ExecutorService接口方法的用法。在这个例子中,如何创建一个执行器服务并在执行器中执行一个任务。我们使用Executors.newSingleThreadExecutor()方法来创建一个ExecutorService,使用一个工作线程来执行任务。
//*/*
/* ExecutorService interface Example
/* @author javaguides.net
/*
/*/
public class ExecutorServiceExample {
public static void main(String[] args) {
System.out.println("Thread main started");
// Create a task
Runnable task = () -> {
for (int i = 0; i < 5; i++) {
System.out.println("[" + Thread.currentThread().getName() + "] " + "Message " + i);
}
};
ExecutorService executorService = Executors.newSingleThreadExecutor();
executorService.execute(task);
executorService.shutdown();
System.out.println("Thread main finished");
}
}
输出:
Thread main started
Thread main finished
[pool-1-thread-1] Message 0
[pool-1-thread-1] Message 1
[pool-1-thread-1] Message 2
[pool-1-thread-1] Message 3
[pool-1-thread-1] Message 4
让我们了解一下execute()
和submit()
方法之间的区别。
ExecutorService
接口访问submit()
和execute()
,因为它也扩展了Executor接口,该接口声明了execute()
方法。ExecutorService为关闭一个执行器提供了两种方法--shutdown()。
shutdown() - 当shutdown()
方法在一个执行者服务上被调用时,它停止接受新任务,等待以前提交的任务执行,然后终止执行者。
shutdownNow() - 这个方法会中断正在运行的任务,并立即关闭执行器。
我们应该在程序的末尾添加关闭代码,这样它就会优雅地退出 -
executorService.shutdown();
让我们使用Executors.newFixedThreadPool(int nThreads)
方法创建一个线程池,重用固定数量的线程在一个共享的无界队列中运行。
在前面的例子中,我们创建了一个ExecutorService
,它使用一个工人线程。但当我们创建一个线程池并在线程池中并发执行多个任务时,ExecutorService
的真正威力才会显现出来。
下面的例子显示了如何创建一个使用线程池的执行器服务,并同时执行多个任务 -
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
//*/*
/* ExecutorService interface Example
/*
/* @author javaguides.net
/*
/*/
public class ExecutorServiceExample {
public static void main(String[] args) {
System.out.println("Thread main started");
// Create a task
Runnable task1 = () -> {
for (int i = 0; i < 5; i++) {
System.out.println("[" + Thread.currentThread().getName() + "] " + "Message " + i);
}
};
// Create a task
Runnable task2 = () -> {
for (int i = 0; i < 5; i++) {
System.out.println("[" + Thread.currentThread().getName() + "] " + "Message " + i);
}
};
// Create a task
Runnable task3 = () -> {
for (int i = 0; i < 5; i++) {
System.out.println("[" + Thread.currentThread().getName() + "] " + "Message " + i);
}
};
// Create a task
Runnable task4 = () -> {
for (int i = 0; i < 5; i++) {
System.out.println("[" + Thread.currentThread().getName() + "] " + "Message " + i);
}
};
ExecutorService executorService = Executors.newFixedThreadPool(2);
executorService.execute(task1);
executorService.execute(task2);
executorService.execute(task3);
executorService.execute(task4);
System.out.println("Thread main finished");
executorService.shutdown();
}
}
输出:
Thread main started
Thread main finished
[pool-1-thread-1] Message 0
[pool-1-thread-1] Message 1
[pool-1-thread-1] Message 2
[pool-1-thread-1] Message 3
[pool-1-thread-1] Message 4
[pool-1-thread-1] Message 0
[pool-1-thread-1] Message 1
[pool-1-thread-1] Message 2
[pool-1-thread-1] Message 3
[pool-1-thread-1] Message 4
[pool-1-thread-1] Message 0
[pool-1-thread-1] Message 1
[pool-1-thread-1] Message 2
[pool-1-thread-1] Message 3
[pool-1-thread-1] Message 4
[pool-1-thread-2] Message 0
[pool-1-thread-2] Message 1
[pool-1-thread-2] Message 2
[pool-1-thread-2] Message 3
[pool-1-thread-2] Message 4
在上面这个例子中,我们创建了2个线程并执行了4个任务。看看输出,只有2个线程pool-1-thread-1和pool-1-thread-2被重用来执行4个任务。
###参考
https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ExecutorService.html
版权说明 : 本文为转载文章, 版权归原作者所有 版权申明
原文链接 : https://www.javaguides.net/2018/09/executorservice-interface-in-java.html
内容来源于网络,如有侵权,请联系作者删除!