Java 创建线程而从不启动它是否会影响性能?

Java 创建线程而从不启动它是否会影响性能?,java,multithreading,performance,Java,Multithreading,Performance,我正在研究一个现有的Java代码库,它有一个扩展线程的对象,还包含一些与线程本身的操作相关的其他属性和方法。在以前版本的代码库中,线程始终是一个实际的、重量级的线程,它以线程开始。开始,等待线程。加入,诸如此类 我目前正在重构代码库,在当前版本中,并不总是需要对象的Thread功能(但由于对象中包含的其他功能,对象本身是需要的;在许多情况下,即使线程本身没有运行,对象本身也是可用的)。因此,在某些情况下,应用程序创建这些对象(扩展Thread),而从不对其调用.start(),纯粹将其用于其他属

我正在研究一个现有的Java代码库,它有一个扩展
线程的对象,还包含一些与线程本身的操作相关的其他属性和方法。在以前版本的代码库中,线程始终是一个实际的、重量级的
线程
,它以
线程开始。开始
,等待
线程。加入
,诸如此类

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

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


我试图通过一些web搜索来确定答案,但很难确定查询的目标,因为搜索引擎通常无法区分
线程
对象和实际的Java线程。

您可以实现
可运行
,而不是扩展
线程

public class MyRunnableClass implements Runnable {

    // Your stuff...

    @Override
    public void run() {
        // Thread-related stuff...
    }

}
当您需要运行
对象
以充当
线程时,只需使用:

Thread t = new Thread(new MyRunnableClass());
t.start();

您可以实现
Runnable
,而不是扩展
Thread

public class MyRunnableClass implements Runnable {

    // Your stuff...

    @Override
    public void run() {
        // Thread-related stuff...
    }

}
当您需要运行
对象
以充当
线程时,只需使用:

Thread t = new Thread(new MyRunnableClass());
t.start();

每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");
        }
    }
}
该对象的使用量比您从读取源代码中预期的要多一些,但每个对象仍有大约600字节


注意:Throwable还使用了比您通过阅读Java源代码所期望的更多的内存。根据创建堆栈时堆栈的大小,可以增加500-2000字节。

每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");
        }
    }
}
该对象的使用量比您从读取源代码中预期的要多一些,但每个对象仍有大约600字节


注意:Throwable还使用了比您通过阅读Java源代码所期望的更多的内存。根据创建堆栈时堆栈的大小,它可能会增加500-2000字节。

正如其他人所指出的:性能在这里不是问题

我将更多地关注“良好设计”方法。当您不打算调用
start()
时,扩展线程毫无意义。你看:你写代码来表达你的意图

扩展线程而不将其用作线程,这只会带来混乱。每一位未来的代码读者都会问“这是为什么?”

因此,要专注于直接的设计。我会更进一步:不要仅仅转向Runnable,继续使用线程。相反:了解ExecutorServices,以及如何提交任务、未来等等


“裸铁”线程(和可运行线程)类似于20年前的概念。到目前为止,Java提供了更好的东西。因此,如果你真的想改进你的代码库:研究这些新的抽象概念,找出它们在哪里使用是有意义的。

正如其他人所指出的:性能在这里不是问题

我将更多地关注“良好设计”方法。当您不打算调用
start()
时,扩展线程毫无意义。你看:你写代码来表达你的意图

扩展线程而不将其用作线程,这只会带来混乱。每一位未来的代码读者都会问“这是为什么?”

因此,要专注于直接的设计。我会更进一步:不要仅仅转向Runnable,继续使用线程。相反:了解ExecutorServices,以及如何提交任务、未来等等


“裸铁”线程(和可运行线程)类似于20年前的概念。到目前为止,Java提供了更好的东西。所以,如果你真的很想改进你的代码库:看看这些新的抽象概念,看看它们在哪里使用是有意义的。

我不知道仅仅实例化对象是否已经为线程的堆栈分配了内存,但是如果线程不是线程,你为什么还要继承线程呢?但是即使线程本身没有运行,对象本身也是可用的“-在我看来,这是一个糟糕的设计。我认为您应该分离一些功能并将其放在其他地方。唯一的副作用是在
ThreadLocal
s@MauricePerry:它可以同步或异步进行一些簿记。如果是异步执行,则线程将接收通过InputStream运行的命令;如果它是同步完成的,那么可以通过直接调用对象的方法来完成,这样就不需要线程了。在创建对象时,它总是异步使用,因此使对象成为