溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

jvm線程變化是怎樣的

發布時間:2021-12-17 13:47:41 來源:億速云 閱讀:245 作者:iii 欄目:開發技術

這篇文章主要介紹“jvm線程變化是怎樣的”,在日常操作中,相信很多人在jvm線程變化是怎樣的問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”jvm線程變化是怎樣的”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!

jvm線程是維護了線程的狀態。new,running,waiting,timed waiting,blocked,terminated。我們通過jstack等工具查看的時候,線程狀態就是上面的一種。jvm本身是做了一種抽象,我們現在從一個典型的方法,來跟蹤查看一下jvm內部又是怎么做狀態變化的。

sleep方法入手

   
public static native void sleep(long millis) throws InterruptedException;

sleep是一個native 方法,我們通過jvm原來來進行跟著(源碼來自openjdk11)。根據jni的規范,我們通過包名或者是jni的注冊方式找到了對應的聲明。

static JNINativeMethod methods[] = {
   {"start0",           "()V",        (void *)&JVM_StartThread},
   {"stop0",            "(" OBJ ")V", (void *)&JVM_StopThread},
   {"isAlive",          "()Z",        (void *)&JVM_IsThreadAlive},
   {"suspend0",         "()V",        (void *)&JVM_SuspendThread},
   {"resume0",          "()V",        (void *)&JVM_ResumeThread},
   {"setPriority0",     "(I)V",       (void *)&JVM_SetThreadPriority},
   {"yield",            "()V",        (void *)&JVM_Yield},
   {"sleep",            "(J)V",       (void *)&JVM_Sleep},
   {"currentThread",    "()" THD,     (void *)&JVM_CurrentThread},
   {"countStackFrames", "()I",        (void *)&JVM_CountStackFrames},
   {"interrupt0",       "()V",        (void *)&JVM_Interrupt},
   {"isInterrupted",    "(Z)Z",       (void *)&JVM_IsInterrupted},
   {"holdsLock",        "(" OBJ ")Z", (void *)&JVM_HoldsLock},
   {"getThreads",        "()[" THD,   (void *)&JVM_GetAllThreads},
   {"dumpThreads",      "([" THD ")[[" STE, (void *)&JVM_DumpThreads},
   {"setNativeName",    "(" STR ")V", (void *)&JVM_SetNativeThreadName},
};

接下來我們要跟蹤的就是JVM_Sleep了。我們一點一點來解析這個方法。首先這里有宏定義。

JVM_ENTRY(void, JVM_Sleep(JNIEnv* env, jclass threadClass, jlong millis))

我們展開JVM_ENTRY。

#define JVM_ENTRY(result_type, header)                               \
extern "C" {                                                         \
 result_type JNICALL header {                                       \
   JavaThread* thread=JavaThread::thread_from_jni_environment(env); \
   ThreadInVMfromNative __tiv(thread);                              \
   debug_only(VMNativeEntryWrapper __vew;)                          \
   VM_ENTRY_BASE(result_type, header, thread)

在ThreadInVMfromNative中,發生了一次線程狀態的變更。

class ThreadInVMfromNative : public ThreadStateTransition {
public:
 ThreadInVMfromNative(JavaThread* thread) : ThreadStateTransition(thread) {
   trans_from_native(_thread_in_vm);
 }
 ~ThreadInVMfromNative() {
   trans_and_fence(_thread_in_vm, _thread_in_native);
 }
};

在構造方法中把JavaThread的**thread->thread_state()**狀態變為了_thread_in_vm。在析構函數中把狀態改成了_thread_in_native。這里的__tiv是一個本地對象,只有在棧銷毀的時候才會觸發析構,也就是說這里的轉為_thread_in_native只不過是一瞬間的事情。展開頭結束后,我們再繼續往后觀察。

  JavaThreadSleepState 
jtss(thread);

在這個構造方法中。把**java_thread->threadObj()**的狀態變為了
java_lang_Thread::SLEEPING

  static void set_thread_status(JavaThread* 
java_thread,
                               java_lang_Thread::ThreadStatus state) {
   java_lang_Thread::set_thread_status(java_thread->threadObj(), state);
 }

這里對應的就是java的線程的狀態了。在往下走就直接設置**thread->osthread()**的狀態為sleep。

    ThreadState old_state = thread->osthread()->get_state();
   thread->osthread()->set_state(SLEEPING);

狀態到這里全部設置完成。

狀態梳理

通過上面的代碼,我們可以發現最核心的就是JavaThread的這個對象,他本身代表的jvm中的線程狀態。會標識線程是在vm還是線程是在java或者在native。具體的狀態如下

enum JavaThreadState {
 _thread_uninitialized     =  0, // should never happen (missing initialization)
 _thread_new               =  2, // just starting up, i.e., in process of being initialized
 _thread_new_trans         =  3, // corresponding transition state (not used, included for completness)
 _thread_in_native         =  4, // running in native code
 _thread_in_native_trans   =  5, // corresponding transition state
 _thread_in_vm             =  6, // running in VM
 _thread_in_vm_trans       =  7, // corresponding transition state
 _thread_in_Java           =  8, // running in Java or in stub code
 _thread_in_Java_trans     =  9, // corresponding transition state (not used, included for completness)
 _thread_blocked           = 10, // blocked in vm
 _thread_blocked_trans     = 11, // corresponding transition state
 _thread_max_state         = 12  // maximum thread state+1 - used for statistics allocation
};

這個類同時那種java線程狀態的引用。就是java_thread->threadObj()。這個對應的是java的線程狀態,這個也是我們jstack看到的狀態。

"main" #1 prio=5 os_prio=31 tid=0x00007fee9b809000 nid=0xe03 waiting on condition [0x0000700008d65000]
  java.lang.Thread.State: TIMED_WAITING (sleeping)
at java.lang.Thread.sleep(Native Method)
at com.company.Sleep.main(Sleep.java:7)

為什么輸出的是timed_waiting(sleep),這個主要是因為格式化輸出的原因。

    if(status == THREAD_STATUS_NEW){
     return "NEW";
   }else if(status == THREAD_STATUS_RUNNABLE){
     return "RUNNABLE";
   }else if(status == THREAD_STATUS_SLEEPING){
     return "TIMED_WAITING (sleeping)";
   }else if(status == THREAD_STATUS_IN_OBJECT_WAIT){
     return "WAITING (on object monitor)";
   }else if(status == THREAD_STATUS_IN_OBJECT_WAIT_TIMED){
     return "TIMED_WAITING (on object monitor)";
   }else if(status == THREAD_STATUS_PARKED){
     return "WAITING (parking)";
   }else if(status == THREAD_STATUS_PARKED_TIMED){
     return "TIMED_WAITING (parking)";
   }else if(status == THREAD_STATUS_BLOCKED_ON_MONITOR_ENTER){
     return "BLOCKED (on object monitor)";
   }else if(status == THREAD_STATUS_TERMINATED){
     return "TERMINATED";
   }
   return "UNKNOWN";
 }

在狀態格式化的時候,把sleeping的歸類成為TIMED_WAITING (sleeping)。于此同時Java Thread還拿著系統的線程thread->osthread()。

到此,關于“jvm線程變化是怎樣的”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

jvm
AI

亚洲午夜精品一区二区_中文无码日韩欧免_久久香蕉精品视频_欧美主播一区二区三区美女