標籤:阻塞 線程
線程狀態(五種狀態)
Java 線程的生命週期包括建立,就緒,運行,阻塞,死亡5 個狀態。一個 Java 線程總是處於這 5 個生命週期狀態之一,並在一定條件下可以在不同狀態之間進行轉換 。
建立狀態 (New Thread)
在 Java 語言中使用 new操作符建立一個線程後,該線程僅僅是一個Null 物件,它具備了線程的一些特徵,但此時系統沒有為其分配資源,這時的線程處於建立狀態。
就緒狀態 (Runnable)
使用 start()方法啟動一個線程後,系統為該線程分配了除 CPU 外的所需資源,使該線程處於就緒狀態。此外,如果某個線程執行了 yield() 方法,那麼該線程會被暫時剝奪 CPU 資源,重新進入就緒狀態。
運行狀態 (Running)
Java運行系統通過調度選中一個處於就緒狀態的線程,使其佔有 CPU 並轉為運行狀態。此時,系統真正執行線程的 run() 方法。
阻塞狀態 (Blocked)
一個正在啟動並執行線程因某些原因不能繼續運行時,它就進入阻塞狀態。
這些原因包括:當執行了某個線程對象的suspend()、sleep()等阻塞類型的方法時,該線程對象會被置入一個阻塞集(Blocked Pool)內,等待被喚醒(執行 resume()方法)或是因為逾時而時自動蘇醒;
當多個線程試圖進入某個同步地區(synchronized)時,沒能進入該同步地區的線程會被置入鎖定集(Lock Pool),直到獲得該同步地區的鎖,進入就緒狀態;
當線程執行了某個對象的 wait() 方法時,線程會被置入該對象的等待集(Wait Pool)中,直到執行了該對象的 notify()方法,wait()/notify()方法的執行要求線程首先擷取到該對象的鎖。
死亡狀態 (Dead)
線程在 run() 方法執行結束後進入死亡狀態。此外,如果線程執行了 interrupt() 或 stop() 方法,那麼它也會以異常退出的方式進入死亡狀態。
停止線程(兩種方式)
1、自然終止:線程體正常執行完畢
2、外部幹涉
1)線程類中 定義線程體使用的標識。2)線程體使用該標識。3)提供對外的方法,改變該標識。4) 外部根據條件調用該方法即可
注意:避免使用Thread類自己提供的stop()(具有不安全性)、suspend()(具有固有的死結現象)、resume() 等方法
package Threadstate;/** * 停止線程 * @author liguodong */public class Demo01 { public static void main(String[] args) { Study s = new Study(); new Thread(s).start();//啟動 //外部幹涉 for(int i=0;i<100;i++) { if(50==i)//外部幹涉(並不是非常準確,還要看CPU) { s.stop(); } System.out.println("main....-->"+i); } } }class Study implements Runnable{ //1、線程類中,定義線程體使用的標識 private boolean flag = true; @Override public void run() { //2、線程體使用該標識 while(flag) { System.out.println("Study thread...."); } } //3、對外提供方法改變標識 public void stop() { this.flag = false; }}
線程阻塞
1、join:合并線程
2、yield:暫停自己的線程 static方法
3、sleep:指定的毫秒數內讓當前正在執行的線程休眠(暫停執行),不會釋放鎖。
(1)與時間相關,如倒計時
(2)類比網路延時
package Threadstate;/** * 線程阻塞: join合并線程 */public class Demo02 extends Thread{ @Override public void run() { for(int i=0;i<100;i++) { System.out.println("join..."+i); } } public static void main(String[] args) throws InterruptedException { Demo02 demo = new Demo02(); Thread t = new Thread(demo);//新生 t.start();//就緒 //cpu調度運行 for(int i=0;i<100;i++) { if(50==i) { t.join();//main阻塞 } System.out.println("main..."+i); } }}
package Threadstate;/** * yield:暫停自己的線程 static方法 * @author liguodong */public class Demo03 extends Thread{ public static void main(String[] args) { Demo03 demo = new Demo03(); Thread t = new Thread(demo);//新生 t.start();//就緒 //cpu調度運行 for(int i=0; i<1000; i++) { if(i%20==0) { //在main線程中,暫停本線程main //本方法寫在那個線程體裡面就停止那個線程,如果在run裡面暫停 Demo03。 Thread.yield();//靜態方法(並沒有嚴格意義上的暫停,可能CPU又調度到它) } System.out.println("main..."+i); } } @Override public void run() { for(int i=0; i<1000; i++) { System.out.println("yield..."+i); } }}
package Threadstate;import java.text.SimpleDateFormat;import java.util.Date;/** * sleep:指定的毫秒數內讓當前正在執行的線程**休眠**(暫停執行),不會釋放鎖。 * 倒計時 * 1、倒數十個數,1秒內列印一個 * 2、倒計時 */public class Demo04 { public static void main(String[] args) throws InterruptedException { //test01(); test02(); } //倒數十個數,1秒內列印一個 public static void test01() throws InterruptedException { int num = 10; while(true) { System.out.println(num--); Thread.sleep(1000);//暫停 if(num<=0) { break; } } } //倒計時 public static void test02() throws InterruptedException { //new Date()目前時間 System.currentTimeMillis()也表示目前時間 Date endTime = new Date(System.currentTimeMillis()+10*1000);//目前時間往後10秒 long end = endTime.getTime();//擷取結束時間的長整型 while(true) { //輸出 System.out.println(new SimpleDateFormat("HH:mm:ss").format(endTime)); //構建下一秒的時間 endTime = new Date(endTime.getTime()-1000);//減一秒 endTime依次遞減 //等待1秒 Thread.sleep(1000);//暫停 //10秒以內繼續 否則退出 end-10000目前時間 if(end-10000>endTime.getTime()) { break; } } } }
package Threadstate;/** * sleep類比網路延時 線程不安全的類 結果可能不準確 */public class Demo05 { public static void main(String[] args) { //真實角色 Web12306 web = new Web12306(); //代理 Thread t1 = new Thread(web,"德瑪西亞"); Thread t2 = new Thread(web,"卡特琳娜"); Thread t3 = new Thread(web,"德邦總管"); //啟動線程 t1.start(); t2.start(); t3.start(); }}class Web12306 implements Runnable{ private int num = 50; @Override public void run() { while(true) { if(num<=0) { break;//跳出迴圈 } try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+"搶到了倒數第"+num--+"張"); } }}
Java線程狀態、線程停止、線程阻塞