线程池中的可运行与线程内和线程池中的可运行有啥区别
Posted
技术标签:
【中文标题】线程池中的可运行与线程内和线程池中的可运行有啥区别【英文标题】:What is Difference between Runnable in a ThreadPool vs Runnable inside a Thread and in a ThreadPool线程池中的可运行与线程内和线程池中的可运行有什么区别 【发布时间】:2019-12-29 19:10:56 【问题描述】:这有什么区别?请参阅选项 1 和选项 2。因为我遇到了麻烦,因为它们好像是一样的。它们运行正确
Thread
ThreadPoolExecutor executor = (ThreadPoolExecutor) Executors.newFixedThreadPool(4);
Thread callLogsThread = new Thread(new CallLogsRunnable());
Thread contactsThread = new Thread(new ContactsRunnable());
/*option 1**/
executor.submit(new ContactsRunnable());
executor.submit(new CallLogsRunnable());
/*option 2**/
executor.submit(contactsThread);
executor.submit(callLogsThread);
/*option 3**/
contactsThread.start();
contactsThread.join();
callLogsThread.start();
callLogsThread.join();
executor.shutdown();
更新:我添加了选项 3。现在选项 1 和选项 3 之间有什么区别。因为我知道选项 2 是废话。谢谢
【问题讨论】:
Thread implements Runnable
,这通常被认为是一个错误。使用Thread#run()
,就像你的执行程序在这里所做的那样,除了在内存中有额外的对象外,与直接调用runnable没有什么不同。
【参考方案1】:
从功能/行为的角度来看,没有区别。在Thread
对象上调用run()
将调用作为构造函数参数传递的Runnable
;看到javadocThread::run()
。
从效率的角度来看,第二个选项创建了不必要的Thread
对象。这会降低性能,增加内存利用率并增加 GC 负载。
(效率影响会很小,但由于Thread
对象没有实现任何目标......请不要这样做。)
从可读性/可维护性的角度来看,第二个选项会引起任何有经验的 Java 程序员阅读您的代码时的“这到底是怎么回事”的反应。你不想要那个。必须弄清楚“奇怪”代码在做什么是浪费人们的时间。
您添加了第三个选项,您可以在其中 start()
线程,而不是使用线程池中的现有线程。
这比选项 1 和 2 都差。您现在为每个任务启动一个新线程,而不是使用线程池。这效率要低得多。线程启动和退出的开销以数千个时钟周期来衡量...
【讨论】:
非常感谢先生提供了非常丰富的答案。希望我可以投票。干杯【参考方案2】:正如评论所说,选项 2) 仅适用于 Thread
实现 Runnable
,其中 run
方法是线程应该执行的操作。
如果您将Thread
传递给执行程序,它将调用Thread
s run()
方法 - 但实际的Thread
本身不会有任何好处。所以选项 2) 是错误的。
如果您想在线程中直接启动Runnable
,请使用callLogsThread.start()
- 然后不要忘记在线程完成时使用join()
。
【讨论】:
/*选项 2**/contactsThread.start();联系人线程.join(); callLogsThread.start(); callLogsThread.join();如果先生这样做怎么办?这和选项1有什么区别?以上是关于线程池中的可运行与线程内和线程池中的可运行有啥区别的主要内容,如果未能解决你的问题,请参考以下文章