Java 就CPU和内存利用率而言,new Thread().sleep与Thread.sleep相比有多差?

Java 就CPU和内存利用率而言,new Thread().sleep与Thread.sleep相比有多差?,java,multithreading,profiling,Java,Multithreading,Profiling,我知道应该在静态上下文中访问睡眠。然而,我需要更多的投入,以便我可以向管理层捍卫这一点。我现在处理的大多数遗留代码都使用新的Thread().sleep,而不是Thread.sleep 这有多糟 for (int c = 0; c < 5; c++) { new Thread().sleep(5000); } 结果(线程睡眠): 它只是文盲编程,就这么简单。这同样适用于以这种方式调用任何静态方法,它不仅限于Thread.sleep()。它带来了无意义的空间和时间成本,但更糟糕的是

我知道应该在静态上下文中访问睡眠。然而,我需要更多的投入,以便我可以向管理层捍卫这一点。我现在处理的大多数遗留代码都使用新的Thread().sleep,而不是Thread.sleep

这有多糟

for (int c = 0; c < 5; c++) {
    new Thread().sleep(5000);
}
结果(线程睡眠):


它只是文盲编程,就这么简单。这同样适用于以这种方式调用任何静态方法,它不仅限于Thread.sleep()。它带来了无意义的空间和时间成本,但更糟糕的是,它暴露了程序员在概念上的重大误解。我不会花太多精力回去修复所有出现的问题,但我肯定会对相关人员进行重新教育。

如果我了解Java如何正确处理静态方法,第一个方法除了创建新的线程对象外,还会调用静态版本的sleep()。使用第二种方法几乎总是更好的,因为可以理解,方法是静态的,它是针对类而不是实例调用的


如果您能够快速找到/替换这些代码语句,我认为这是值得的。然而,由于这两种代码都能工作,我认为这不是你应该过分担心的事情。

它们做的是相同的事情,并且在这两种情况下,方法都是静态的

新线程()中睡眠(5000),不清楚实际发生了什么,因为静态方法是从实例调用的。也就是说,它的功能与
Thread.sleep(5000)相同,其优点是透明

还不清楚是当前线程将被休眠,因此有人可能会合理地怀疑是当前线程还是新创建的线程将被休眠;它实际上是当前线程

如果允许使用第一种样式,您可以选择以下样式:

Thread anotherThread = new Thread();
那么以后呢,

anotherThread.sleep(5000);
这也与Thread.sleep(5000)相同,并实际将当前线程置于睡眠状态。但这根本不清楚发生了什么


第二种情况下的样式更可取,因为它避免了这些陷阱,以及与创建新实例相关的任何性能损失。因此,应始终使用它。

它有多糟糕?从性能的角度来看,可能不是很糟糕

我的理解是,线程实例化的昂贵部分只有在调用
thread.start()
时才会发生。但是,在构建
线程
对象的过程中会发生大量工作:

  • 初始化一组字段
  • 进行安全检查
  • 等等
如果您想要证据证明这是一个重大的性能问题,那么您需要分析您的应用程序。(我怀疑这是否意义重大。)

但修复起来应该不难/不贵。。。除非你身处一个每一次改变都很艰难/代价高昂的世界。。。或者,除非您的应用程序使用ThreadGroup或可继承的ThreadLocals执行一些非常奇怪/不正常的操作

我的主要抱怨是,它像一头南行的母牛的北端一样丑陋。与调用<代码>新字符串(…)>代码>一致。



我不认为你的基准显示太多。创建不需要的线程的开销可能在一微秒左右。那是在噪音中。此外,您测量内存使用情况的方法是完全错误的。
totalMemory()
freemory()
方法为您提供上次GC运行时记录的内存统计信息。

除了前面已经说过的:如果您已经在重写一些遗留代码,这可能是表示睡眠的最惯用、最直接的方法(当然,您可以使用不同的时间单位):


实际上它的价格相当高:

new-Thread()
实际上是一个昂贵的调用(当然没有
Thread.start()
那么贵),但它涉及堆栈爬网、几个同步块、几个安全检查、继承线程局部变量的副本等。在安全经理的管理下,它也会变得混乱

在1.3之前,未启动的线程用于导致严重的内存泄漏。。。现在它仍然是一个问题:ThreadGroup报告错误的threadCount并可能变成负值。。。但最糟糕的是仍然会导致泄漏,因为除非手动丢弃,否则在所有线程退出后,ThreaGroup不会膨胀(
destroy()
)。后者可能会有问题,因为它需要等待所有线程正确退出,然后调用
destroy()
。听起来很简单,但对于托管环境(即容器),这是一个实际问题

编辑因为不清楚ThreadGroup可以是子类,以便覆盖
未捕获的异常(Thread t,Throwable e)
并处理Throwable。这使得ThreadGroup类持有对类加载器的引用,问题是真实的。(不仅仅是轻微的单一物体泄漏)


总的来说,未启动的线程自Java诞生以来就一直在对其进行窃听,最好是替换代码。这比我写回复所花的时间要少(主要是为了让大家了解相信的免费初始化)。

在这两种情况下,睡眠时间都比
new Thread()的“开销”长几个数量级。
。尽管如此,我还是同意EJP下面所说的。@对于我的回答,我感到非常抱歉。。我没有看到java标签。。我在C#的上下文中回答。。我的错误:(@Shekhar:别担心,这不是针对个人的。否决票严格来说是因为答案不适用于这里。是的,我知道..应该注意到..无论如何,好的一点是我得到了同侪压力徽章..失去8分的东西:)看起来最好使用
线程。睡眠(25000)
。仅仅为了更换所有发生的故障,真的需要那么多能量吗
Total memory: 5177344
Free memory: 4990904
===========================
Used memory: 186440
===========================
Used memory: 205136
===========================
Used memory: 205136
===========================
Used memory: 205136
===========================
Used memory: 205136
===========================
Total memory: 5177344
Free memory: 4972208
===========================
Time elapsed: 24938 milliseconds
Total memory: 5177344
Free memory: 4990904
===========================
Used memory: 186440
===========================
Used memory: 186440
===========================
Used memory: 204848
===========================
Used memory: 204848
===========================
Used memory: 204848
===========================
Total memory: 5177344
Free memory: 4972496
===========================
Time elapsed: 24938 milliseconds
Thread anotherThread = new Thread();
anotherThread.sleep(5000);
TimeUnit.SECONDS.sleep(5);