Java中使用ThreadGroup相比单独创建线程有什么好处?

23

许多方法,例如stop()resume()suspend()等已被弃用。

因此,使用ThreadGroup创建线程是否有用?

5个回答

24

在拥有数千个线程的大型应用服务器中,使用 ThreadGroup 可以是一种有用的诊断技巧。如果你的线程被逻辑分组在一起,那么当你获取堆栈跟踪时,你可以看到有问题的线程所属的组别(例如"Tomcat 线程"、 "MDB 线程"、 "线程池 X" 等),这可以帮助你更容易地追踪和解决问题。


2
我曾经考虑过这个问题,但我认为它并没有比适当地命名线程更有优势。然而,如果您无法修改线程名称,或者您有一个按组聚合监视线程活动的工具,那么情况就不同了。 - Andrzej Doyle
4
有道理,但是额外的结构可以很有用,比如将CPU使用率按线程组聚合。 - skaffman
1
我在一个非常大的企业应用程序中使用它们,原因是这样。我本可以自己跟踪它们,但这将迫使我编写大量代码来管理我的集合内容,当线程完成、死亡等时。 - Fredrik

17

3
遗憾的是,我认为当前问题的信息投票结果未能满足全球社区的要求。《Effective Java 第二版》第73条。 - Greg Mattes
6
这似乎没有回答问题,问题是“为什么我要使用它?”而不是“我应该使用它吗?” - user253751
ThreadGroupExecutor并不是互斥的。您可以使用ExecutorsThreadFactory一起创建带有ThreadGroup的线程。 - cambunctious
1
确实,它们不是互相排斥的:在ThreadFactory中创建的新线程可以注入ThreadGroup,正如所接受的答案所述,可以用于对线程进行分组,但是一般来说,仍然有充足的(最近的)证据支持应避免使用ThreadGroup API。 请参考:https://wiki.sei.cmu.edu/confluence/display/java/THI01-J.+Do+not+invoke+ThreadGroup+methods。 - Greg Mattes

12
有点补充之前提供的答案(大约6年前)。但是,虽然并发API提供了许多结构,ThreadGroup仍然有用。它提供以下功能:
  1. 对线程进行逻辑组织(用于诊断目的)。
  2. 您可以interrupt()组中的所有线程。(中断是完全可以的,不像suspend()resume()stop())。
  3. 您可以设置组中线程的最大优先级。(不确定这有多广泛的用途,但是你有它)。
  4. ThreadGroup设置为守护进程。(因此,添加到其中的所有新线程都将是守护线程)。
  5. 允许覆盖其uncaughtExceptionHandler,以便如果组中的一个线程引发异常,则拥有回调来处理它。
  6. 提供一些额外的工具,如获取线程列表、您有多少个活动线程等。在拥有一组工作线程或某种线程池时很有用。

太深入的解释了,谢谢@jbx - Ram Kowsu

3
简短回答是:不,实际上没有什么好处。如果你想将工作线程分组,最好使用ExecutorService。如果你想快速计算概念组中有多少个线程是活动的,你仍然需要逐个检查每个线程(因为ThreadGroup.activeCount()只是一个估计值,如果你的代码正确性依赖于它的输出,它就没用了)。
我敢说,如今唯一从中获得的好处除了语义上的隔离外,就是作为一个组的一部分构建的线程将拾取守护进程标志和基于组的合理名称。而且使用这个作为在构造函数调用中填充一些原始数据的快捷方式(通常你只需要编写一次,因为你可能会在循环和/或方法调用中启动线程)。
所以,我真的看不到任何使用它的强烈理由。几个月前,我尝试过使用它,但失败了。
编辑-我认为潜在的一个用途可能是,如果你正在运行一个SecurityManager,并且想断言只有在同一组中的线程才能相互中断。即使这样也很边缘,因为默认实现总是对任何非系统线程组中的线程返回true。如果你正在实现自己的SecurityManager,你有可能根据任何其他标准(包括存储线程的典型技术,因为它们被创建)来决定其决策。

如何在创建线程时将Thread存储到集合中。我不知道如何判断线程何时被创建。 - Tom Hawtin - tackline
你需要使用 new Thread(...) 这一段代码。:-) 由于线程只能在构造时显式地分配到一个组中,因此可以合理地假设 OP 的代码是显式地创建它们的。如果他没有自己调用构造函数,那么他无法更改线程组。 - Andrzej Doyle
作为一组构建的线程将会继承守护进程标志。但是这并不完全正确,守护线程是从父线程而非线程组继承的。 - Alan Bateman

1

非常好的答案,适用于@skaffman。我想再增加一个优点:

线程组有助于一次性操作在其中定义的所有线程。


“Suspend”是一个已被弃用的选项,正如@jbx的回答中所述。 - jontro
没有启动线程组的方法。您必须逐个启动每个线程。 - preeth

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接