簡體   English   中英

Java線程中的大量過睡會在沒有GC干擾和低機器負載的情況下發生

[英]Large oversleep in Java thread occurs without GC interference and with low machine load

在我正在開發的一個相當復雜的應用程序中,我在一個線程中有以下代碼:

long T = System.currentTimeMillis();
Thread.sleep(waitNow);
T = System.currentTimeMillis()-T;
if (T > waitNow*5) {
    System.out.println("Overslept "+T+" > "+waitNow);
}

這個線程在某些情況下過度睡眠並產生如下輸出:

Overslept 10010 > 10

請注意:我知道Thread.sleep方法的合同允許它睡過頭但是這個行為很奇怪,因為過度睡眠的大小(10秒而不是10毫秒)。

線程大多數睡眠時間接近指定時間(11-15ms)但是由於某種原因,當應用程序運行時,它會睡得更久(10秒+)並且可能會在幾分鍾內執行此操作(可能同樣多次)每分鍾兩次或三次)。

該線程是普通優先級線程。

應用程序中總共有大約35個線程。

我已經使用了jconsole並驗證了垃圾收集器在這些睡眠期間沒有運行,並且當GC運行時它非常快(jconsole報告它需要大約30-50ms)。

該應用程序被分配256m的內存(-Xmx),但堆沒有使用接近該數量(可能約30米)和一個測試應用程序專門推動VM的內存限制,同時另一個線程試圖睡眠沒有遇到同樣的問題。

這個特定的線程發送UDP消息,但是它以相對較低的速率發送這些消息(每秒大約20x 510字節消息--10k / sec)。

線程不會中斷,因為它繼續完成計時並打印出關於睡過頭的消息。

JRE是1.7.0_45 build 18運行在2013年Retina Macbook pro 13“運行OSX Mavericks上。

由於我的測試應用程序也沒有在這個應用程序同時睡過頭(事實上測試應用程序根本沒有睡過頭)這表明它不是時鍾更新問題,並且是這個app / JVM特別的東西但是我我想不出會導致這種情況的任何事情,事實上除了在機器上消耗大量資源外,我想不出任何方式讓Java內部的一個線程影響另一個線程睡眠的時間,這導致我懷疑它在JVM或OS中是奇怪的。

問題是:

有誰知道線程睡過頭的可能原因是什么?

應用程序(或其他任何東西)可以做什么,不會涉及JVM中使用的高內存或可能影響此問題的機器上的高CPU使用率?

我在練習中遇到過類似情況,結果證明JVM 安全點存在問題。

對於診斷,您可以使用以下選項:

  • -XX:+PrintGCApplicationStoppedTime - 它打印所有STW暫停,不僅與GC有關
  • -XX:+PrintSafepointStatistics - 打印安全點詳細信息
  • -XX:PrintSafepointStatisticsCount=1 - 使JVM報告每個安全點

在我的情況下,根本原因是在應用程序代碼中(可能代碼已經觸發了JIT中的一些錯誤)。

這類問題通常與操作系統有關。 這是一個常見問題,有一些工具可以衡量您的日程安排有多糟糕。 最值得注意的是http://www.jhiccup.com/但是,5 - 50毫秒的打嗝更為常見。

多秒延遲可能是某些磁盤IO或非常嚴重的事情,例如您的線程可能被交換到磁盤。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM