<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
Java的執行緒狀態描述放在Thread
類裡面的列舉類State
中.總共包含了6中狀態(從出生到死亡)。
public enum State { /** * 尚未啟動的執行緒的執行緒狀態 (沒有start) */ NEW, /** * 可執行執行緒的執行緒狀態,是可以執行的執行緒狀態(並不是在執行) * 這個狀態在Java虛擬機器器中進行,但它可能等待來自作業系統的其他資源,比如CPU。 * 內部包含了兩個狀態 【RUNNING】,【READY】這兩個狀態是可以互相流轉的 * 呼叫了start後執行緒就處於 READY 狀態 ,等待作業系統分配CPU時間片,分配後進入 RUNNING 狀態。 * 當呼叫 yield() 方法後,只是謙讓的允許當前執行緒讓出 CPU ,但是不一定讓,由作業系統決定,如果讓 * 了當前執行緒就會進入 READY 狀態,等待系統分配CPU時間片再次進入 RUNNING 狀態。 */ RUNNABLE, /** * 阻塞狀態。 * 執行緒阻塞,等待監視器鎖的狀態,獲取監視器鎖後會進入 RUNNABLE 狀態 * 當發生執行緒鎖競爭狀態下,沒有獲取到鎖的執行緒會被掛起進入阻塞狀態,比如synchronized鎖。 */ BLOCKED, /** * 等待執行緒的執行緒狀態 * 執行緒呼叫以下方法會處於等待狀態:Object.wait()不超時、Thread.join()不超時等方法 * 一個處於等待狀態的執行緒正在等待另一個執行緒執行特定動作,例如: * 一個執行緒呼叫了Object.wait()方法在一個物件上正在等待另一個執行緒呼叫Object.nofify()或者 * Object.nofifyAll()方法開啟那個物件 * 一個呼叫了Thread.join()方法的執行緒正在等待指定執行緒終止 */ WAITING, /** * 具有指定等待時間的等待執行緒的執行緒狀態,呼叫一下方法會處於這個狀態: Object.wait() 超時、 * Thread.join()超時 Thread.sleep(long) 等方法 */ TIMED_WAITING, /** * 已終止執行緒的執行緒狀態 * 執行緒執行完畢或者發生異常終止執行 */ TERMINATED; }
public class ThreadStatusDemo { public static void main(String[] args) throws InterruptedException { // 測試 NEW RUNNABLE TERMINATED Thread terminated_thread = new Thread(() -> { long start = System.currentTimeMillis(); // 執行三秒 ,列印TERMINATED_THREAD執行緒runnable狀態 while (System.currentTimeMillis()-start<3000){} }, "TERMINATED_THREAD"); // NEW Thread.State state = terminated_thread.getState(); System.out.println(terminated_thread.getName()+" :state = " + state); terminated_thread.start(); TimeUnit.SECONDS.sleep(1); // RUNNABLE Thread.State state1 = terminated_thread.getState(); System.out.println(terminated_thread.getName()+"state1 = " + state1); TimeUnit.SECONDS.sleep(5); Thread.State state2 = terminated_thread.getState(); // TERMINATED System.out.println(terminated_thread.getName()+"state2 = " + state2); // RUNNABLE new Thread(() -> { while (true) { } }, "Runnle_Thread").start(); // TIMED_WAITING new Thread(() -> { while (true) { try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } } }, "Time_Waiting_Thread").start(); // WAITING new Thread(() -> { while (true) { synchronized (ThreadStatusDemo.class) { try { ThreadStatusDemo.class.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } } }, "Waiting_Thread").start(); // 這兩個看誰先搶佔到cpu獲得鎖,另一個就blocked // timed_waiting new Thread(new BlockedDemo(), "Blocke01_Thread").start(); // blocked new Thread(new BlockedDemo(), "Blocke02_Thread").start(); } static class BlockedDemo extends Thread { @Override public void run() { synchronized (BlockedDemo.class) { while (true) { try { TimeUnit.SECONDS.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } } } } }
Java
啟動一個執行緒呼叫start
方法,start方法內部呼叫了 start0()
native方法。
public synchronized void start() { . . . boolean started = false; try { // 呼叫native方法 start0(); started = true; } finally { try { if (!started) { group.threadStartFailed(this); } } catch (Throwable ignore) { /* do nothing. If start0 threw a Throwable then it will be passed up the call stack */ } } }
這個測試是為了驗證上圖的正確性,只貼了部分.
檢視指引:
在jvm.cpp
找到JVM_StartThread
方法。發現是先建立個 JavaThread
作為本地執行緒然後啟動這個本地執行緒(藉助os【thread.cpp】,因為jvm是跨平臺的,這裡是以linux-os為範例)
JVM_ENTRY(void, JVM_StartThread(JNIEnv* env, jobject jthread)) JVMWrapper("JVM_StartThread"); JavaThread *native_thread = NULL; bool throw_illegal_thread_state = false; { MutexLocker mu(Threads_lock); if (java_lang_Thread::thread(JNIHandles::resolve_non_null(jthread)) != NULL) { throw_illegal_thread_state = true; } else { jlong size = java_lang_Thread::stackSize(JNIHandles::resolve_non_null(jthread)); size_t sz = size > 0 ? (size_t) size : 0; // 先建立一個JavaThread native_thread = new JavaThread(&thread_entry, sz); if (native_thread->osthread() != NULL) { native_thread->prepare(jthread); } } } if (throw_illegal_thread_state) { THROW(vmSymbols::java_lang_IllegalThreadStateException()); } assert(native_thread != NULL, "Starting null thread?"); if (native_thread->osthread() == NULL) { delete native_thread; if (JvmtiExport::should_post_resource_exhausted()) { JvmtiExport::post_resource_exhausted( JVMTI_RESOURCE_EXHAUSTED_OOM_ERROR | JVMTI_RESOURCE_EXHAUSTED_THREADS, "unable to create new native thread"); } THROW_MSG(vmSymbols::java_lang_OutOfMemoryError(), "unable to create new native thread"); } // 然後啟動這個本地執行緒 thread.cpp Thread::start(native_thread); JVM_END
JavaThread 建立執行緒:
JavaThread::JavaThread(ThreadFunction entry_point, size_t stack_sz) : Thread() #if INCLUDE_ALL_GCS , _satb_mark_queue(&_satb_mark_queue_set), _dirty_card_queue(&_dirty_card_queue_set) #endif // INCLUDE_ALL_GCS { if (TraceThreadEvents) { tty->print_cr("creating thread %p", this); } initialize(); _jni_attach_state = _not_attaching_via_jni; set_entry_point(entry_point); os::ThreadType thr_type = os::java_thread; thr_type = entry_point == &compiler_thread_entry ? os::compiler_thread : os::java_thread // 呼叫os(作業系統)建立個執行緒 os::create_thread(this, thr_type, stack_sz); _safepoint_visible = false; . . . }
thread.cpp 啟動執行緒:
// tips: 啟動執行緒的方法 void Thread::start(Thread* thread) { trace("start", thread); // Start is different from resume in that its safety is guaranteed by context or // being called from a Java method synchronized on the Thread object. if (!DisableStartThread) { if (thread->is_Java_thread()) { // Initialize the thread state to RUNNABLE before starting this thread. // Can not set it after the thread started because we do not know the // exact thread state at that time. It could be in MONITOR_WAIT or // in SLEEPING or some other state. // tips:啟動之後設定執行緒的狀態為 可執行狀態 RUNNABLE java_lang_Thread::set_thread_status(((JavaThread*)thread)->threadObj(), java_lang_Thread::RUNNABLE); } // 藉助作業系統啟動執行緒 os::start_thread(thread); } }
執行緒的終止不要簡單的呼叫 stop
方法,這個方法和其他的執行緒控制方法(suspend
,resume
)一樣都是過期了不建議使用的,這些方法都是不安全的。 例如stop()
方法在結束一個執行緒的時候並不保證執行緒資源的正常釋放,因此可能導致出現一些不確定的狀態。 按照人類邏輯來理解:T1執行緒呼叫方法修改T2執行緒的狀態,但是T2現在在做什麼T1是不清楚的,所以強制他關閉就是不安全的,就好比在Linux
中使用 kill -9
殺掉一個程序。
interrupt()
方法只是修改了被中斷執行緒的中斷標誌 ,並沒有做什麼過分的事兒。就像平時寫程式碼的時候修改某物件的標誌,物件自己通過標誌類決定執行什麼邏輯。這裡也是一樣,interrupt()
方法修改中斷標誌,被中斷的執行緒,自己決定做什麼事兒(中斷或者不中斷都是被中斷執行緒自己決定的,外部只是通知他,不是強迫他)。追一下原始碼。
1.Java呼叫interrupt
方法
2.通過指引找到 jvm.cpp#JVM_Interrupt
方法
thread.cpp interrupt 借用作業系統。直接通過系統呼叫 interrupt void Thread::interrupt(Thread* thread) { trace("interrupt", thread); debug_only(check_for_dangling_thread_pointer(thread);) // tips: 呼叫作業系統的interrupt方法 os::interrupt(thread); }
這裡還是以os_linux.cpp為例最終呼叫osthread的set_interrupted修改狀態
這裡就印證了上方的 Thread.interrupt()
只是修改了執行緒的一個標誌位 ,並沒有做什麼過分的事兒。
interrupted
與isInterrupted
這兩個放在一起是因為他們底層都是呼叫的同一個native方法isInterrupted()
只是給了不同的入參。 再就是,有過面試官問到他兩的區別,所以乾脆放在一起。首先說結論 ,isInterrupted()
會返回執行緒的中斷狀態,interrupted()
不僅會返回中斷狀態,而且如果執行緒處於狀態狀態還會將執行緒終端狀態復位(清除中斷狀態)。
os_linux.cpp的is_interrupted()
方法印證了上面說的isInterrupted()
會返回執行緒的中斷狀態,interrupted()
不僅會返回中斷狀態,而且如果執行緒處於狀態狀態還會將執行緒終端狀態復位(清除中斷狀態)。
在Java
中只要丟擲了InnterruptException
異常的方法都對執行緒進行了復位。先理順下為什麼要這麼做:檢視下基本上丟擲InnterruptException
異常的方法都是執行緒阻塞方法,比如sleep()
,wait()
,join()
。這類方法執行後執行緒會處於TIMED_WAITING
或者WAITING
狀態,處於這類狀態的執行緒是不受控的(執行緒喪失了對自己的主導,需要其他的執行緒喚醒,或者阻塞時間到達才能擁有自己的主導權),這個時候執行緒中斷,執行緒自己卻沒辦法處理。甚至可能永遠等不到釋放而無法執行中斷。所以,線上程是中斷狀態下,執行方法讓執行緒阻塞,就要丟擲一個異常告訴外界 ,我現在是阻塞狀態,並且將中斷標記復位,方便外界進行處理(例如中斷執行緒的執行或者繼續阻塞方法),相當於給了外界一個改變執行緒狀態的入口。 以sleep()
為例追蹤下原始碼:
通過指引找到 jcm.cpp#JVM_Sleep
方法入口就直接判斷執行緒的中斷狀態了 ,is_interrupted()
上面介紹過了,引數為true
就是清除中斷標誌並且返回清除之前的中斷狀態。這裡執行緒是中斷狀態的就直接丟擲 InnterruptException sleep interrupted
異常了。
到此這篇關於Java執行緒生命週期的終止與復位的文章就介紹到這了,更多相關Java執行緒生命週期內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45