我正在研究一个现有的Java代码库,该代码库具有扩展了Thread
的对象,并且还包含许多其他与线程本身的操作有关的属性和方法。在以前的代码库版本中,线程始终是实际的,重量级的Thread
,以Thread.start
开头,以Thread.join
等,等等。
我目前正在重构代码库,在当前版本中,并非总是需要对象的Thread
功能(但是由于对象中包含的其他功能,因此对象本身是必需的;即使线程本身未运行,它仍然可用)。因此,在某些情况下,应用程序会创建这些对象(扩展了Thread
),而从不对其调用.start()
,仅将它们用于其他属性和方法。
将来,应用程序可能需要创建比以前更多的这些对象,以至于我可能需要担心性能。显然,创建和启动大量实际线程将是性能的噩梦。同一件事是否适用于从未启动的Thread
对象?也就是说,仅创建Thread
是否需要任何操作系统资源或大型Java资源?还是仅在实际Thread
被.start
使无起始Thread
对象安全使用的情况下才使用资源?可以重构代码以将与非线程相关的功能拆分为单独的功能,但是如果这样做完全没有意义,我不想进行大型重构。
我已经尝试通过几次网络搜索来确定答案,但是由于搜索引擎通常无法将Thread
对象与实际的Java线程区分开,因此很难针对查询进行查询。
答案 0 :(得分:4)
您可以实现Runnable
而不是扩展Thread
。
public class MyRunnableClass implements Runnable {
// Your stuff...
@Override
public void run() {
// Thread-related stuff...
}
}
只要您需要运行Object
使其表现为Thread
,只需使用:
Thread t = new Thread(new MyRunnableClass());
t.start();
答案 1 :(得分:2)
正如其他人所指出的:性能在这里不是问题。
我将更多地关注“好的设计”方法。当您不打算调用start()
时,扩展Thread根本没有任何意义。您会看到:您编写代码来传达您的意图。
扩展线程而不将其用作线程,只能传达混乱。将来您的代码的每一个新读者都会想知道“为什么”?
因此,请集中精力进行简单的设计。而且我会更进一步:不要只是转向 Runnable ,而是继续使用线程。相反:了解ExecutorServices,以及如何提交任务,Future等。
“裸铁”线程(和Runnable)就像20岁的概念。 Java现在提供了更好的东西。因此,如果您真的很想改善代码库,请:研究这些新的抽象概念,以找出应该使用的地方。
答案 2 :(得分:1)
您每GB内存可以创建约150万个对象。
import java.util.LinkedList;
import java.util.List;
class A {
public static void main(String[] args) {
int count = 0;
try {
List<Thread> threads = new LinkedList<>();
while (true) {
threads.add(new Thread());
if (++count % 10000 == 0)
System.out.println(count);
}
} catch (Error e) {
System.out.println("Got " + e + " after " + count + " threads");
}
}
}
对于Oracle Java 8使用-Xms1g -Xmx1g
,该过程几乎停顿了
1 GB - 1780000
2 GB - 3560000
6 GB - 10690000
该对象的使用量比您阅读源代码所期望的要多,但每个对象仍约为600字节。
注意:Throwable还使用了比阅读Java源代码预期更多的内存。可以再增加500-2000字节,具体取决于创建堆栈时的堆栈大小。