欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Thread.sleep(0)的寫法原理深入解析

 更新時間:2022年12月27日 14:04:05   作者:JAVA旭陽  
這篇文章主要為大家介紹了Thread.sleep(0)的寫法原理深入解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪

前言

最近在網(wǎng)上看到了一段代碼,讓我感到很迷茫。他在代碼中使用了 Thread.sleep(0),讓線程休眠時間為0秒,具體代碼如下。

int i = 0;
while (i<10000000) {
    // business logic
    //prevent long time gc
    if (i % 3000 == 0) {
        try {
            Thread.sleep(0);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

sleep了0秒,不就是不睡覺嗎?我的第一反應(yīng)是這段代碼沒什么用,但是看到他的注釋又引起了我的興趣。經(jīng)過一番研究,看似無用的一段代碼,其實大有文章。

探索分析

為了找到原因,首先去看下sleep方法的javadoc,如下:

Causes the currently executing thread to sleep (temporarily ceaseexecution) for the specified number of milliseconds, subject tothe precision and accuracy of system timers and schedulers. The thread does not lose ownership of any monitors.

顯然沒有得到正確的答案,最后在詢問作者說是使用Thread.sleep(0)可以暫時釋放CPU時間線。

時間片循環(huán)調(diào)度算法

在操作系統(tǒng)中,CPU有很多競爭策略。Unix系統(tǒng)采用時間片循環(huán)調(diào)度算法。在該算法中,所有進程都被分組到一個隊列中。操作系統(tǒng)按順序為每個進程分配一定的時間,即允許進程運行的時間。如果在時間片結(jié)束時進程仍在運行,則CPU將被剝奪并分配給另一個進程,如果進程在時間片內(nèi)阻塞或結(jié)束,則CPU立即切換。調(diào)度程序所要做的就是維護一個就緒進程表。當(dāng)進程用完時間片時,它將被移到隊列的末尾。

上面的代碼中存在死循環(huán)。作者希望一直用一個線程來處理業(yè)務(wù)邏輯。如果Thread.sleep(0)不使用主動放棄CPU時間片,線程資源會一直被占用。眾所周知,GC 線程具有低優(yōu)先級,因此Thread.sleep(0)用于幫助 GC 線程嘗試競爭 CPU 時間片。但是為什么作者說可以防止long time GC呢?這就講到JVM的垃圾回收原理了。

GC的安全點

HotSpot虛擬機為例,JVM并不會在代碼指令流的任何位置暫停以啟動垃圾回收,而是強制執(zhí)行必須到達安全點才暫停。換句話說,在到達安全點之前,JVM 不會為 GC STOP THE WORLD。

JVM 會在一些循環(huán)跳轉(zhuǎn)和方法調(diào)用上設(shè)置安全點。不過,為了避免安全點過多帶來的沉重負(fù)擔(dān),HotSpot虛擬機還有一個針對循環(huán)的優(yōu)化措施。如果循環(huán)次數(shù)少,執(zhí)行時間不宜過長。因此,默認(rèn)情況下不會將使用 int 或更小數(shù)據(jù)類型作為索引值的循環(huán)放置在安全點中。這種循環(huán)稱為可數(shù)循環(huán)。相應(yīng)地,使用long或更大范圍的數(shù)據(jù)類型作為索引值的循環(huán)稱為未計數(shù)循環(huán),將被放置在安全點。

但是,我們這里正好有一個可數(shù)循環(huán),所以我們的代碼不會放在安全點。因此,GC線程必須等到線程執(zhí)行完畢,才能執(zhí)行到最近的安全點。但如果使用Thread.sleep(0),則可以在代碼中放置一個安全點。我們可以看下HotSpotsafepoint.cpp源碼中的注釋,做除了說明。

// Begin the process of bringing the system to a safepoint.
// Java threads can be in several different states and are
// stopped by different mechanisms:
//
//  1. Running interpreted
//     The interpeter dispatch table is changed to force it to
//     check for a safepoint condition between bytecodes.
//  2. Running in native code
//     When returning from the native code, a Java thread must check
//     the safepoint _state to see if we must block.  If the
//     VM thread sees a Java thread in native, it does
//     not wait for this thread to block.  The order of the memory
//     writes and reads of both the safepoint state and the Java
//     threads state is critical.  In order to guarantee that the
//     memory writes are serialized with respect to each other,
//     the VM thread issues a memory barrier instruction
//     (on MP systems).  In order to avoid the overhead of issuing
//     a memory barrier for each Java thread making native calls, each Java
//     thread performs a write to a single memory page after changing
//     the thread state.  The VM thread performs a sequence of
//     mprotect OS calls which forces all previous writes from all
//     Java threads to be serialized.  This is done in the
//     os::serialize_thread_states() call.  This has proven to be
//     much more efficient than executing a membar instruction
//     on every call to native code.
//  3. Running compiled Code
//     Compiled code reads a global (Safepoint Polling) page that
//     is set to fault if we are trying to get to a safepoint.
//  4. Blocked
//     A thread which is blocked will not be allowed to return from the
//     block condition until the safepoint operation is complete.
//  5. In VM or Transitioning between states
//     If a Java thread is currently running in the VM or transitioning
//     between states, the safepointing code will wait for the thread to
//     block itself when it attempts transitions to a new state.

可以看上面的第2點 Running in native code,而Thread.sleep(long millis)是一種native方法。

總結(jié)

Thread.sleep(0)不是什么無用的代碼。sleep 方法可用于在 java 代碼中放置一個安全點。可以提前在長循環(huán)中觸發(fā)GC,避免GC線程長時間等待,從而避免達到拉長GC時間的目的。

以上就是Thread.sleep(0)的寫法原理深入解析的詳細(xì)內(nèi)容,更多關(guān)于Thread.sleep(0)寫法原理的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

最新評論