创建线程并且从不启动它会对性能产生影响吗?

时间:2018-11-14 08:16:41

标签: java multithreading performance

我正在研究一个现有的Java代码库,该代码库具有扩展了Thread的对象,并且还包含许多其他与线程本身的操作有关的属性和方法。在以前的代码库版本中,线程始终是实际的,重量级的Thread,以Thread.start开头,以Thread.join等,等等。

我目前正在重构代码库,在当前版本中,并非总是需要对象的Thread功能(但是由于对象中包含的其他功能,因此对象本身是必需的;即使线程本身未运行,它仍然可用)。因此,在某些情况下,应用程序会创建这些对象(扩展了Thread),而从不对其调用.start(),仅将它们用于其他属性和方法。

将来,应用程序可能需要创建比以前更多的这些对象,以至于我可能需要担心性能。显然,创建和启动大量实际线程将是性能的噩梦。同一件事是否适用于从未启动的Thread对象?也就是说,仅创建Thread是否需要任何操作系统资源或大型Java资源?还是仅在实际Thread.start使无起始Thread对象安全使用的情况下才使用资源?可以重构代码以将与非线程相关的功能拆分为单独的功能,但是如果这样做完全没有意义,我不想进行大型重构。

我已经尝试通过几次网络搜索来确定答案,但是由于搜索引擎通常无法将Thread对象与实际的Java线程区分开,因此很难针对查询进行查询。

3 个答案:

答案 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字节,具体取决于创建堆栈时的堆栈大小。