Java 春季多线程
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/29492124/
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
Multithreading in spring
提问by Elis.jane
I am trying to get into spring multithreading and I have few questions.
我正在尝试使用 spring 多线程,但我有几个问题。
I have runnable method in ThreadRating class. Now I am not sure about the best way of using it.
我在 ThreadRating 类中有 runnable 方法。现在我不确定使用它的最佳方式。
option 1 I found:
选项 1 我发现:
private void updateRating() {
ExecutorService executor = Executors.newFixedThreadPool(10);
for (int i = 0; i < 10; i++) { // test
// thread part
Runnable worker = new ThreadRating(path, i, products.get(i), dao, fileHandler);
executor.execute(worker);
}
executor.shutdown();
try {
executor.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
} catch (InterruptedException e) {
log.error("There was an error when ending threads");
System.exit(1);
}
System.out.println("Finished all threads");
}
This seem to be running fine. After the for loop, it waits until threads are finished and ends.
这似乎运行良好。在 for 循环之后,它等待线程完成并结束。
Second option I tried
我试过的第二个选项
private TaskExecutor taskExecutor;
public UpdateBO(TaskExecutor taskExecutor) {
this.taskExecutor = taskExecutor;
}
private void updateRating() {
for (int i = 0; i < 10; i++) { // test
Runnable worker = new ThreadRating(path, i, products.get(i), dao, fileHandler);
taskExecutor.execute(worker);
}
// wait for threads to be finished before you go any further ??
}
And in xml file I have
在 xml 文件中我有
<beans:bean id="taskExecutor"
class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
<beans:property name="corePoolSize" value="5" />
<beans:property name="maxPoolSize" value="10" />
<beans:property name="queueCapacity" value="25" />
<beans:property name="waitForTasksToCompleteOnShutdown" value="true" />
</beans:bean>
<beans:bean id="updateBO" class="UpdateBO">
<beans:constructor-arg ref="taskExecutor" />
</beans:bean>
And here are my questions:
这是我的问题:
- Is there any difference between these two options? Speed, memory, possible leaks? Or are they the same just written differently?
- Do I need to shutdown the pool when using webservice? I know that in the second option I don't have to, but is it the same when using webservice?
- When using second option - how should I tell to wait there until all jobs are finished? In the first option I just shut the pool down and wait to finish. But in the second option the code request is finished before the tasks are completed.
executor.execute(worker);
- just to clarify. This is not actually creating a new thread, but it adds task to a queue and if the queue is full it waits right on this line in the code until there is free place?
- 这两个选项有什么区别吗?速度、内存、可能的泄漏?或者它们是相同的只是写法不同?
- 使用 webservice 时是否需要关闭池?我知道在第二个选项中我不必这样做,但是使用 webservice 时是否相同?
- 使用第二个选项时 - 我应该如何告诉等待所有作业完成?在第一个选项中,我只是关闭池并等待完成。但在第二个选项中,代码请求在任务完成之前完成。
executor.execute(worker);
- 只是为了澄清。这实际上并不是创建一个新线程,而是将任务添加到队列中,如果队列已满,它会在代码中的这一行上等待,直到有空闲位置?
Thanks for helping me understand.
谢谢你帮我理解。
采纳答案by Alex Salauyou
Main difference: in option 1) you create new executor on every
updateRating()
call, in option 2) executor is created once on deployment time, you feed the same single executor with new jobs. Second approach is much better.Why do you need to shut down the executor? Creating new executors and shutting them down to wait until task is processed is antipattern. Remember, that executors are created in order to control system resourcesand should be treated such. (E. g. you have DB connection pool of 50 connections - so to serve DB access you create executor of 50 threads - to avoid connection limit exceed. Or you have 24 cores on server and need to parallelize work in the best possible way).
And, as I mentioned in comment, in some environments (such as app servers) you often have no rights to shut down executor. Such attempt will produce
SecurityException
.If you need to wait until workers finish their jobs, wrap every job with
Callable
instead ofRunnable
, then from main thread call correspondingfuture.get()
- and it will block until job finishes. Timeouts are supported. ExampleAbsolutely right. Threads are created and destroyed by executor itself, when it thinks is best time to. Try to monitor your app with jvisualvmto see how it happens.
主要区别:在选项 1) 中,您在每次
updateRating()
调用时创建新的执行程序 ,在选项 2) 中,执行程序在部署时创建一次,您为同一个执行程序提供新作业。第二种方法要好得多。为什么需要关闭执行器?创建新的 executors 并关闭它们以等待任务被处理是反模式。请记住,执行程序是为了控制系统资源而创建的,应该这样对待。(例如,您有 50 个连接的 DB 连接池 - 因此为了服务 DB 访问,您创建了 50 个线程的执行程序 - 以避免超出连接限制。或者您在服务器上有 24 个内核,需要以最佳方式并行化工作) .
而且,正如我在评论中提到的,在某些环境(例如应用服务器)中,您通常无权关闭执行程序。这样的尝试会产生
SecurityException
。如果你需要等到工人完成他们的工作,用
Callable
而不是包装每个工作Runnable
,然后从主线程调用相应的future.get()
- 它会阻塞直到工作完成。支持超时。例子绝对正确。线程由 executor 自己创建和销毁,当它认为是最好的时候。尝试使用jvisualvm监控您的应用程序,看看它是如何发生的。
回答by Fritz Duchardt
1.) Option 1 is badly implemented since you define your executor service locally and close it after each use. This defeats the purpose of creating a thread pool - it needs to be a global object, so Option 2 is the way to go.
1.) 选项 1 实施不当,因为您在本地定义了执行程序服务并在每次使用后关闭它。这违背了创建线程池的目的——它需要是一个全局对象,所以选项 2 是可行的方法。
2.) You don't need to shut down the executor service when calling a web service. If the webservice does not respond the call will eventually time out and the thread fill complete execution. If you shut down the executor service, it won't be available for the next call.
2.) 调用web服务时不需要关闭executor服务。如果 Web 服务没有响应,调用最终将超时并且线程填充完成执行。如果您关闭 executor 服务,它将无法用于下一次调用。
3.) If you need some form of notifcation once your thread has finised, you should use Callablein conjuction with Futuresinstead.
3.) 如果您在线程完成后需要某种形式的通知,则应将Callable与Futures结合使用。
4.) Your executor service has a maximum of 10 threads allocated, it won't spawn off more than those. If all of them are busy, you task will idle until one of those threads becomes available.
4.) 您的执行程序服务最多分配了 10 个线程,它不会产生更多线程。如果它们都忙,您的任务将空闲,直到其中一个线程可用。