<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                # 線程生命周期(狀態) 當線程被創建并啟動以后,它既不是一啟動就進入了執行狀態,也不是一直處于執行狀態。 在線程的生命周期中,它要經過新建(New)、就緒(Runnable)、運行(Running)、阻塞 (Blocked)和死亡(Dead)5 種狀態。尤其是當線程啟動以后,它不可能一直"霸占"著 CPU 獨自 運行,所以 CPU 需要在多條線程之間切換,于是線程狀態也會多次在運行、阻塞之間切換 ## 新建狀態(NEW) 當程序使用 new 關鍵字創建了一個線程之后,該線程就處于新建狀態,此時僅由 JVM 為其分配 內存,并初始化其成員變量的值 ## 就緒狀態(RUNNABLE) 當線程對象調用了 start()方法之后,該線程處于就緒狀態。Java 虛擬機會為其創建方法調用棧和 程序計數器,等待調度運行。 ## 運行狀態(RUNNING) 如果處于就緒狀態的線程獲得了 CPU,開始執行 run()方法的線程執行體,則該線程處于運行狀 態。 ## 阻塞狀態(BLOCKED) 阻塞狀態是指線程因為某種原因放棄了 cpu 使用權,也即讓出了 cpu timeslice,暫時停止運行。 直到線程進入可運行(runnable)狀態,才有機會再次獲得 cpu timeslice 轉到運行(running)狀 態。阻塞的情況分三種: ### 等待阻塞(o.wait->等待對列) 運行(running)的線程執行 o.wait()方法,JVM 會把該線程放入等待隊列(waitting queue) 中。 ### 同步阻塞(lock->鎖池) 運行(running)的線程在獲取對象的同步鎖時,若該同步鎖被別的線程占用,則 JVM 會把該線 程放入鎖池(lock pool)中。 ### 其他阻塞(sleep/join) 運行(running)的線程執行 Thread.sleep(long ms)或 t.join()方法,或者發出了 I/O 請求時, JVM 會把該線程置為阻塞狀態。當 sleep()狀態超時、join()等待線程終止或者超時、或者 I/O 處理完畢時,線程重新轉入可運行(runnable)狀態。 ## 線程死亡(DEAD) 線程會以下面三種方式結束,結束后就是死亡狀態。 ### 正常結束 1. run()或 call()方法執行完成,線程正常結束。 ### 異常結束 2. 線程拋出一個未捕獲的 Exception 或 Error。 ### 調用 stop 3. 直接調用該線程的 stop()方法來結束該線程—**該方法通常容易導致死鎖**,不推薦使用。 ![](https://img.kancloud.cn/e0/a4/e0a4009f38cb99e6a923a50d0654b002_631x224.png) # 終止線程的四種方式 ## 正常運行結束 程序運行結束,線程自動結束。 ## 使用退出標志退出線程 一般 run()方法執行完,線程就會正常結束,然而,常常有些線程是伺服線程。它們需要長時間的 運行,只有在外部某些條件滿足的情況下,才能關閉這些線程。使用一個變量來控制循環,例如: 最直接的方法就是設一個 boolean 類型的標志,并通過設置這個標志為 true 或 false 來控制 while 循環是否退出,代碼示例: ```java /** * @program: ThreadDemo * @description: 使用退出標志退出線程 * @author: hs96.cn@Gmail.com * @create: 2020-08-27 15:10 */ public class ThreadSafe extends Thread { public volatile boolean exit = false; public void run() { while (!exit) { //do something } } public static void main(String[] args) { ThreadSafe threadSafe = new ThreadSafe(); threadSafe.run(); } } ``` 定義了一個退出標志 exit,當 exit 為 true 時,while 循環退出,exit 的默認值為 false.在定義 exit 時,**使用了一個 Java 關鍵字 volatile**,這個關鍵字的目的是使 exit 同步,也就是說在同一時刻只 能由一個線程來修改 exit 的值。 ## Interrupt 方法結束線程 使用 interrupt()方法來中斷線程有兩種情況: ### 線程處于阻塞狀態 如使用了 sleep,同步鎖的 wait,socket 中的 receiver,accept 等方法時, 會使線程處于阻塞狀態。當調用線程的 interrupt()方法時,會拋出 InterruptException 異常。 阻塞中的那個方法拋出這個異常,通過代碼捕獲該異常,然后 break 跳出循環狀態,從而讓 我們有機會結束這個線程的執行。通常很多人認為只要調用 interrupt 方法線程就會結束,實 際上是錯的, 一定要先捕獲 InterruptedException 異常之后通過 break 來跳出循環,才能正 常結束 run 方法。 ### 線程未處于阻塞狀態 使用 isInterrupted()判斷線程的中斷標志來退出循環。當使用 interrupt()方法時,中斷標志就會置 true,和使用自定義的標志來控制循環是一樣的道理。 ```java public class ThreadSafe extends Thread { public void run() { while (!isInterrupted()){ //非阻塞過程中通過判斷中斷標志來退出 try{ Thread.sleep(5*1000);//阻塞過程捕獲中斷異常來退出 }catch(InterruptedException e){ e.printStackTrace(); break;//捕獲到異常之后,執行 break 跳出循環 } } } } ``` ## stop 方法終止線程(線程不安全) 程序中可以直接使用 thread.stop()來強行終止線程,但是 stop 方法是很危險的,就象突然關 閉計算機電源,而不是按正常程序關機一樣,可能會產生不可預料的結果,不安全主要是: thread.stop()調用之后,創建子線程的線程就會拋出 ThreadDeatherror 的錯誤,并且會釋放子 線程所持有的所有鎖。一般任何進行加鎖的代碼塊,都是為了保護數據的一致性,如果在調用 thread.stop()后導致了該線程所持有的所有鎖的突然釋放(不可控制),那么被保護數據就有可能呈 現不一致性,其他線程在使用這些被破壞的數據時,有可能導致一些很奇怪的應用程序錯誤。因 此,并不推薦使用 stop 方法來終止線程。 # start()源碼簡單剖析: 在lang包里的Thread.java找到start()方法可以看到,實際就是native的start0()。 ![](https://img.kancloud.cn/74/2a/742a463bd06c9013d987aa834ed02e6a_937x652.png) 當原生線程初始化完畢,就會調用 Java 線程的 run() 方法。 ![](https://img.kancloud.cn/6a/59/6a590f14eb25e6067a2a7ca191f8ceb2_757x364.png) 其實這種設計技巧是一種模板方法,下面來編寫一個模板方法來體會Thread的start()設計的思想: ## 其中的設計模式 ```java /** * @program: ThreadDemo * @description: 編寫一個模板方法來體會Thread的start()設計的思想 * @author: hs96.cn@Gmail.com * @create: 2020-08-26 */ public abstract class BaseTemplateMethod { public static void main(String[] args) { BaseTemplateMethod t1 = new BaseTemplateMethod() { @Override protected void wrapPrint(String message) { System.out.println("*" + message + "*"); } }; t1.print("Hello Thread"); BaseTemplateMethod t2 = new BaseTemplateMethod() { @Override protected void wrapPrint(String message) { System.out.println("+" + message + "+"); } }; t2.print("Hello Thread"); } public final void print(String message) { System.out.println("#####################"); wrapPrint(message); System.out.println("#####################"); } protected abstract void wrapPrint(String message); } ``` ![](https://img.kancloud.cn/fa/38/fa382e1becfd7c889fffc40a02c745df_1040x224.gif) wrapPrint就相當于start方法,print就相當于run方法。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看