Java 使用 ExecutorService 有什么好处?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3984076/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
What are the advantages of using an ExecutorService?
提问by devnull
What is the advantage of using ExecutorService
over running threads passing a Runnable
into the Thread
constructor?
什么是使用的优势,ExecutorService
通过在一个线程运行Runnable
到Thread
构造函数?
采纳答案by andersoj
ExecutorService
abstracts away many of the complexities associated with the lower-level abstractions like raw Thread
. It provides mechanisms for safely starting, closing down, submitting, executing, and blocking on the successful or abrupt termination of tasks (expressed as Runnable
or Callable
).
ExecutorService
抽象出许多与诸如 raw 等低级抽象相关的复杂性Thread
。它提供了安全启动、关闭、提交、执行和阻止任务成功或突然终止的机制(表示为Runnable
或Callable
)。
From JCiP, Section 6.2, straight from the horse's mouth:
来自JCiP,第 6.2 节,直接从马嘴里说出来:
Executor
may be a simple interface, but it forms the basis for a flexible and powerful framework for asynchronous task execution that supports a wide variety of task execution policies. It provides a standard means of decoupling task submissionfrom task execution, describing tasks asRunnable
. TheExecutor
implementations also provide lifecycle support and hooks for adding statistics gathering, application management, and monitoring. ... Using anExecutor
is usually the easiest path to implementing a producer-consumer design in your application.
Rather than spending your time implementing (often incorrectly, and with great effort) the underlying infrastructure for parallelism, the j.u.concurrent
framework allows you to instead focus on structuring tasks, dependencies, potential parallelism. For a large swath of concurrent applications, it is straightforward to identify and exploit task boundaries and make use of j.u.c
, allowing you to focus on the much smaller subset of true concurrency challenges which may require more specialized solutions.
与其花时间(通常是错误的,并且需要付出很大的努力)实现并行的底层基础架构,该j.u.concurrent
框架使您可以专注于构建任务、依赖项和潜在的并行性。对于大量并发应用程序,识别和利用任务边界并使用 是很简单的j.u.c
,让您可以专注于真正并发挑战的小得多的子集,这可能需要更专业的解决方案。
Also, despite the boilerplate look and feel, the Oracle API page summarizing the concurrency utilitiesincludes some really solid arguments for using them, not least:
此外,尽管样板外观和感觉,总结并发实用程序的Oracle API 页面包含一些使用它们的非常可靠的论据,尤其是:
Developers are likely to already understand the standard library classes, so there is no need to learn the API and behavior of ad-hoc concurrent components. Additionally, concurrent applications are far simpler to debug when they are built on reliable, well-tested components.
开发人员很可能已经了解标准库类,因此无需学习特定并发组件的 API 和行为。此外,当并发应用程序构建在可靠的、经过良好测试的组件上时,它们的调试要简单得多。
This question on SOasks about a good book, to which the immediate answer is JCiP. If you haven't already, get yourself a copy. The comprehensive approach to concurrency presented there goes well beyond this question, and will save you a lot of heartache in the long run.
SO 上的这个问题询问了一本好书,直接回答是 JCiP。如果您还没有,请给自己一个副本。那里提出的全面的并发方法远远超出了这个问题,从长远来看,它将为您省去很多心痛。
回答by Manny
An advantage I see is in managing/scheduling several threads. With ExecutorService, you don't have to write your own thread manager which can be plagued with bugs. This is especially useful if your program needs to run several threads at once. For example you want to execute two threads at a time, you can easily do it like this:
我看到的一个优势是管理/调度多个线程。使用 ExecutorService,您不必编写自己的线程管理器,因为它可能会被错误困扰。如果您的程序需要同时运行多个线程,这将特别有用。例如你想一次执行两个线程,你可以很容易地这样做:
ExecutorService exec = Executors.newFixedThreadPool(2);
exec.execute(new Runnable() {
public void run() {
System.out.println("Hello world");
}
});
exec.shutdown();
The example may be trivial, but try to think that the "hello world" line consists of a heavy operation and you want that operation to run in several threads at a time in order to improve your program's performance. This is just one example, there are still many cases that you want to schedule or run several threads and use ExecutorService as your thread manager.
这个例子可能是微不足道的,但试着认为“hello world”行包含一个繁重的操作,你希望该操作一次在多个线程中运行,以提高程序的性能。这只是一个例子,还有很多情况你想调度或运行多个线程并使用 ExecutorService 作为你的线程管理器。
For running a single thread, I don't see any clear advantage of using ExecutorService.
对于运行单个线程,我没有看到使用 ExecutorService 的任何明显优势。
回答by sun007
Below are some benefits:
以下是一些好处:
- Executor service manage thread in asynchronous way
- Use Future callable to get the return result after thread completion.
- Manage allocation of work to free thread and resale completed work from thread for assigning new work automatically
- fork - join framework for parallel processing
- Better communication between threads
- invokeAll and invokeAny give more control to run any or all thread at once
- shutdown provide capability for completion of all thread assigned work
- Scheduled Executor Services provide methods for producing repeating invocations of runnables and callables Hope it will help you
- Executor 服务以异步方式管理线程
- 使用 Future callable 获取线程完成后的返回结果。
- 管理工作分配以释放线程并从线程转售已完成的工作以自动分配新工作
- fork - 并行处理的连接框架
- 更好的线程间通信
- invokeAll 和 invokeAny 给予更多的控制来同时运行任何或所有线程
- 关闭提供完成所有线程分配工作的能力
- Scheduled Executor Services 提供了产生重复调用 runnables 和 callables 的方法希望它会帮助你
回答by Anil Saha
Prior to java 1.5 version, Thread/Runnable was designed for two separate services
在 java 1.5 版本之前,Thread/Runnable 是为两个独立的服务设计的
- Unit of work
- Execution of that unit of work
- 工作单位
- 该工作单元的执行
ExecutorService decouples those two services by designating Runnable/Callable as unit of work and Executor as a mechanism to execute ( with lifecycling) the unit of work
ExecutorService 通过将 Runnable/Callable 指定为工作单元和 Executor 作为执行(使用生命周期)工作单元的机制来分离这两个服务
回答by Bade
ExecutorService also gives access to FutureTask which will return to the calling class the results of a background task once completed. In the case of implementing Callable
ExecutorService 还可以访问 FutureTask,FutureTask 将在完成后将后台任务的结果返回给调用类。在实现 Callable 的情况下
public class TaskOne implements Callable<String> {
@Override
public String call() throws Exception {
String message = "Task One here. . .";
return message;
}
}
public class TaskTwo implements Callable<String> {
@Override
public String call() throws Exception {
String message = "Task Two here . . . ";
return message;
}
}
// from the calling class
ExecutorService service = Executors.newFixedThreadPool(2);
// set of Callable types
Set<Callable<String>>callables = new HashSet<Callable<String>>();
// add tasks to Set
callables.add(new TaskOne());
callables.add(new TaskTwo());
// list of Future<String> types stores the result of invokeAll()
List<Future<String>>futures = service.invokeAll(callables);
// iterate through the list and print results from get();
for(Future<String>future : futures) {
System.out.println(future.get());
}
回答by Premraj
The following limitations from traditional Thread overcome by Executor framework(built-in Thread Pool framework).
Executor 框架(内置线程池框架)克服了传统线程的以下限制。
- Poor Resource Managementi.e. It keep on creating new resource for every request. No limit to creating resource. Using Executor framework we can reuse the existing resources and put limit on creating resources.
- Not Robust: If we keep on creating new thread we will get
StackOverflowException
exception consequently our JVM will crash. - Overhead Creation of time: For each request we need to create new resource. To creating new resource is time consuming. i.e. Thread Creating > task. Using Executor framework we can get built in Thread Pool.
- 糟糕的资源管理即它不断为每个请求创建新资源。创建资源没有限制。使用 Executor 框架,我们可以重用现有资源并限制创建资源。
- 不健壮:如果我们继续创建新线程,我们将得到
StackOverflowException
异常,因此我们的 JVM 将崩溃。 - 开销创建时间:对于每个请求,我们需要创建新资源。创建新资源是耗时的。即线程创建> 任务。使用 Executor 框架,我们可以在线程池中构建。
Benefits of Thread Pool
线程池的好处
Use of Thread Pool reduces response time by avoiding thread creation during request or task processing.
Use of Thread Pool allows you to change your execution policy as you need. you can go from single thread to multiple thread by just replacing ExecutorService implementation.
Thread Pool in Java application increases stability of system by creating a configured number of threads decided based on system load and available resource.
Thread Pool frees application developer from thread management stuff and allows to focus on business logic.
线程池的使用通过避免在请求或任务处理期间创建线程来减少响应时间。
使用线程池允许您根据需要更改执行策略。您只需替换 ExecutorService 实现即可从单线程变为多线程。
Java 应用程序中的线程池通过创建基于系统负载和可用资源决定的配置数量的线程来提高系统的稳定性。
线程池将应用程序开发人员从线程管理工作中解放出来,并允许专注于业务逻辑。
回答by Evgeni Sergeev
Is it really that expensive to create a new thread?
创建一个新线程真的那么昂贵吗?
As a benchmark, I just created 60,000 threads with Runnable
s with empty run()
methods. After creating each thread, I called its start(..)
method immediately. This took about 30 seconds of intense CPU activity. Similar experiments have been done in response to this question. The summary of those is that if the threads do not finish immediately, and a large number of active threads accumulate (a few thousand), then there will be problems: (1) each thread has a stack, so you will run out of memory, (2) there might be a limit on the number of threads per process imposed by the OS, but not necessarily, it seems.
作为基准,我刚刚创建了 60,000 个Runnable
带有空run()
方法的s线程。创建每个线程后,我start(..)
立即调用它的方法。这花了大约 30 秒的密集 CPU 活动。针对这个问题已经做了类似的实验。综上所述,如果线程没有立即结束,并且大量的活动线程累积(几千个),那么就会出现问题:(1)每个线程都有一个堆栈,所以你会耗尽内存, (2) 操作系统对每个进程的线程数可能有限制,但似乎不一定。
So, as far as I can see, if we're talking about launching say 10 threads per second, and they all finish faster than new ones start, and we can guarantee that this rate won't be exceeded too much, then the ExecutorService doesn't offer any concrete advantage in visible performance or stability. (Though it may still make it more convenient or readable to express certain concurrency ideas in code.) On the other hand, if you might be scheduling hundreds or thousands of tasks per second, which take time to run, you could run into big problems straight away. This might happen unexpectedly, e.g. if you create threads in response to requests to a server, and there is a spike in the intensity of requests that your server receives. But e.g. one thread in response to every user input event (key press, mouse motion) seems to be perfectly fine, as long as the tasks are brief.
因此,据我所知,如果我们谈论的是每秒启动 10 个线程,并且它们的完成速度都比新线程的启动速度快,并且我们可以保证不会超过这个速率太多,那么 ExecutorService在可见的性能或稳定性方面没有提供任何具体的优势。(尽管在代码中表达某些并发思想可能仍然更方便或更易读。)另一方面,如果您可能每秒调度成百上千个任务,这需要时间来运行,您可能会遇到大问题马上。这可能会意外发生,例如,如果您创建线程来响应对服务器的请求,并且您的服务器收到的请求强度出现峰值。但是,例如,响应每个用户输入事件(按键、鼠标移动)的一个线程似乎完全没问题,
回答by Affy
Creating a large number of threads with no restriction to the maximum threshold can cause application to run out of heap memory. Because of that creating a ThreadPool is much better solution. Using ThreadPool we can limit the number of threads can be pooled and reused.
在没有最大阈值限制的情况下创建大量线程可能会导致应用程序耗尽堆内存。因此,创建 ThreadPool 是更好的解决方案。使用 ThreadPool 我们可以限制可以池化和重用的线程数。
Executors framework facilitate process of creating Thread pools in java. Executors class provide simple implementation of ExecutorService using ThreadPoolExecutor.
Executors 框架简化了在 java 中创建线程池的过程。Executors 类使用 ThreadPoolExecutor 提供了 ExecutorService 的简单实现。
Source:
来源: