在CPU和内存利用率方面,与Thread.sleep相比,新的Thread()。睡眠有多糟糕?

时间:2011-03-07 07:01:17

标签: java multithreading profiling

我知道应该在静态环境中访问睡眠。但是我需要更多的输入,所以我可以向管理层辩护。我正在处理的大多数遗留代码现在使用新的Thread()。sleep而不是Thread.sleep。

这有多糟糕?

for (int c = 0; c < 5; c++) {
    new Thread().sleep(5000);
}

与此相比?

for (int c = 0; c < 5; c++) {
    Thread.sleep(5000);
}

编辑:

    final long start = System.currentTimeMillis();
    System.out.println("Total memory: " + Runtime.getRuntime().totalMemory());
    System.out.println("Free memory: " + Runtime.getRuntime().freeMemory());
    System.out.println("===========================");
    for (int c = 0; c < 5; c++) {
        new Thread().sleep(5000);
        System.out.println("Used memory: " + (Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory()));
        System.out.println("===========================");
    }
    System.out.println("Total memory: " + Runtime.getRuntime().totalMemory());
    System.out.println("Free memory: " + Runtime.getRuntime().freeMemory());
    System.out.println("===========================");
    System.out.println("Time elapsed: " + (System.currentTimeMillis() - start) + " milliseconds");

结果(新线程()。睡眠):

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

结果(Thread.sleep):

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

6 个答案:

答案 0 :(得分:9)

这只是文盲编程,简单就是这样。同样适用于调用任何静态方法,它不仅限于Thread.sleep()。它带来了毫无意义的空间和时间成本,但更糟糕的是它背叛了程序员的一个主要的概念误解。我不会投入太多精力来回去修复所有事件,但我肯定会对重新教育相关人员采取一些措施。

答案 1 :(得分:4)

除了已经说过的内容之外:如果你已经在重写一些遗留代码,那么这可能是表达睡眠的最惯用和直接的方式(你当然可以使用不同的时间单位):

TimeUnit.SECONDS.sleep(5);

答案 2 :(得分:2)

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

我的理解是,线程实例化的昂贵部分仅在您调用Thread.start()时发生。但是,在构造Thread对象时会发生相当多的工作:

  • 初始化一堆字段,
  • 进行安全检查,
  • 等等。

如果您想要证明这是一个重大的性能问题,那么您需要对您的应用进行概要分析。 (而且我怀疑它显着。)

但修复它不应该是困难/昂贵的事情......除非你处于一个每个变化都很难/昂贵的世界......或者除非你的应用程序做了一些非常奇怪/使用ThreadGroups或可继承的ThreadLocals破坏东西。

我的主要抱怨是它和南方牛的北端一样难看。与在整个地方调用new String(...)相提并论。


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

答案 3 :(得分:2)

实际上费用相当高:

实际上,

new Thread()是一个昂贵的调用(当然不像Thread.start()那么多)但涉及堆栈爬行,几个同步块,几个安全检查,继承的线程本地的副本和所以。在安全经理下,它也会变得混乱。

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

编辑因为不清楚ThreadGroup可以是子类,以便覆盖uncaughtException(Thread t, Throwable e)并处理throwable。这使得ThreadGroup类保持对类加载器的引用,问题是真实的。 (不只是一个小的单个物体泄漏)

总体上未启动的线程一直在窃听Java,你最好更换代码。它比我写回复所需的时间更少(主要是为了相信免费初始化)。

答案 4 :(得分:1)

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

如果你能够快速找到/替换这些代码语句,我会说这是值得的。但是,由于两个代码都有效,我认为这不是你应该过分担心的事情。

答案 5 :(得分:1)

他们做同样的事情,这两种方法都是静态的。

new Thread().sleep(5000);中,不清楚实际发生了什么,因为静态方法是从实例调用的。也就是说,它在功能上与Thread.sleep(5000);相同,具有透明的好处。

目前还不清楚当前线程是否会被置于休眠状态,因此有人可以合理地猜测它是当前线程还是新创建的线程将被置于睡眠状态;它实际上是当前的线程。

如果允许第一种风格,你可能会遇到类似的事情:

Thread anotherThread = new Thread();

然后稍后

anotherThread.sleep(5000);

这也与Thread.sleep(5000);相同,实际上将当前线程置于休眠状态。但事实上发生的事情并不明显。

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