1、S02E174_01線程狀態與中止線程
1、線程狀態
新生狀態:用new關鍵字和Thread類或子類創建一個線程對象後,該線程對象就處於新生狀態。處於新生狀態的線程有本身的內存空間,經過調用start方法進入就緒狀態(Runnable)
就緒狀態:處於就緒狀態的線程已經具有了運行條件,但尚未分配到CPU,處於線程就緒隊列,等待系統爲其分配CPU。等待狀態並非執行狀態,當系統選定一個等待執行的Thread對象後,它就會從等待執行狀態進入執行狀態,系統挑選的動做稱之爲「CPU調度」。一旦得到CPU,線程就進入運行狀態並自動調用本身的run方法
運行狀態:在運行狀態的線程執行本身的run方法中代碼,直到調用其它方法而終止、或等待某資源而阻塞或完成任務而死亡。若是在給定的時間片內沒有執行結束,就會被系統給換下來回到等待執行狀態。
阻塞狀態:處於運行狀態的線程在某些狀況下,如執行了sleep(睡眠)方法,或等待I/O設備等資源,將讓出CPU並暫時中止本身的運行,進入阻塞狀態。在阻塞狀態的線程不能進入就緒狀態,只有當引發阻塞的緣由消除時,如睡眠時間已到,或等待的I/O設備空閒下來,線程便轉入就緒狀態,從新到就緒隊列中排隊等待,被系統選中後從原來中止的位置開始繼續運行
死亡狀態:死亡狀態是線程生命週期中的最後一個階段。線程死亡的緣由有兩個。一個是正常運行的線程完成了它的所有工做;另外一個是線程被強制性地終止,如經過執行stop或destroy方法來終止一個線程(不推薦使用這兩個方法。前者會產生異常,後者是強制終止,不會釋放鎖。)
2、中止線程
一、天然終止:線程體正常執行完畢
二、外部干涉:
——線程類中定義線程體使用的標識
——線程體使用該標識
——提供對外的方法改變該標識
——外部根據條件調用該方法便可java
package com.test.thread.status; public class TestStatus { public static void main(String[] args) { Study s = new Study(); new Thread(s).start(); //外部干涉 for (int i = 0; i < 100000; i++) { if(50000 == i){//外部干涉 s.stop(); System.out.println("stop...-->>" + i); } } } } class Study implements Runnable{ //線程類中定義線程體使用的標識 private boolean flag = true; @Override public void run() { //線程體使用該標識 while(flag){ System.out.println("study thread..."); } } //對外提供方法改變標識 public void stop(){ this.flag = false; } }
3、S02E176_01線程阻塞2_sleep_倒計時_網絡延時
一、join:合併線程
二、yield:暫停本身的線程(static方法,暫停一下,可能下一毫秒又被調用,這由CPU決定)
三、sleep:休眠,不釋放鎖
——1)與時間相關:倒計時
——2)模擬網絡延時web
package com.test.thread.status; /** * join:合併線程 */ public class TestJoin extends Thread { public static void main(String[] args) throws InterruptedException { TestJoin testJoin = new TestJoin(); Thread t = new Thread(testJoin);//新生狀態 t.start();//就緒狀態 //CPU調度 運行 for (int i = 0; i < 1000; i++) { if(50==i){ t.join();//main阻塞,等待t執行完 } System.out.println("main..."+i); } } @Override public void run() { for (int i = 0; i < 1000; i++) { System.out.println("join..."+i); } } }
package com.test.thread.status; /** * yield:暫停本身的線程(static方法,暫停一下,可能下一毫秒又被調用,這由CPU決定) */ public class TestYield extends Thread { public static void main(String[] args) { TestYield testYield = new TestYield(); Thread t = new Thread(testYield); t.start(); for (int i = 0; i < 1000; i++) { if(0==i%200){ //暫停當前線程 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 com.test.thread.status; import java.text.SimpleDateFormat; import java.util.Date; /** * 倒計時 * 一、倒數10個數,一秒內打印一個 * 二、倒計時 */ public class TestSleep { public static void main(String[] args) throws InterruptedException { test1(); test2(); } /** * 一、倒數10個數,一秒內打印一個 * @throws InterruptedException */ public static void test1() throws InterruptedException{ int num = 10; while(true){ System.out.println(num--); Thread.sleep(1000);//暫停 if(num <= 0){ break; } } } /** * 二、倒計時 * @throws InterruptedException */ public static void test2() throws InterruptedException{ Date endTime = new Date(System.currentTimeMillis() + 10*1000); long end = endTime.getTime(); while(true){ //輸出 System.out.println(new SimpleDateFormat("mm:ss").format(endTime)); //等待一秒 Thread.sleep(1000); //構建下一秒時間 endTime = new Date(endTime.getTime() - 1000); //10秒之內繼續,不然退出 if(end-10000 > endTime.getTime()){ break; } } } }
package com.test.thread.status; /** * sleep模擬網絡延時 * 引發併發問題 ... 路人甲搶到了44 攻城獅搶到了44 ... 路人甲搶到了1 攻城獅搶到了0 黃牛乙搶到了-1 */ public class TestSleep2 { 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;//1到50號 @Override public void run(){ while(true) { if(num <= 0){ break;//跳出循環 } try { Thread.sleep(500);//t一、t二、t3可能都在等待,num可能相同或爲-1 } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + "搶到了" + num--); } } }
4、S02E177_01線程基本信息_優先級
網絡
package com.test.thread.info; public class MyThread implements Runnable { private boolean flag = true; private int num = 0; @Override public void run() { while(flag){ System.out.println(Thread.currentThread().getName()+ "-->>" + num++); } } public void stop(){ flag = !flag; } }
package com.test.thread.info; /** * Thread.currentThread * setName() * getName() * isAlive */ public class InfoDemo { public static void main(String[] args) throws InterruptedException { MyThread it = new MyThread(); Thread proxy = new Thread(it,"挨踢"); proxy.setName("test"); System.out.println(proxy.getName()); System.out.println(Thread.currentThread().getName());//main proxy.start(); System.out.println("啓動後的狀態:" + proxy.isAlive()); Thread.sleep(50); it.stop(); Thread.sleep(100);//stop後,CPU不必定當即中止,休眠一下看一下效果 System.out.println("中止後的狀態:" + proxy.isAlive()); } }
package com.test.thread.info; /** * 優先級:機率,不是絕對的前後順序 * MAX_PRIORITY 10 * NORM_PRIORITY 5(默認) * MIN_PRIORITY 0 * * setPriority() * getPriority() */ public class InfoPriority { public static void main(String[] args) throws InterruptedException { MyThread it1 = new MyThread(); Thread p1 = new Thread(it1,"挨踢1"); MyThread it2 = new MyThread(); Thread p2 = new Thread(it2,"挨踢2"); p1.setPriority(Thread.MIN_PRIORITY); p2.setPriority(Thread.MAX_PRIORITY); p1.start(); p2.start(); Thread.sleep(100); it1.stop(); it2.stop(); } }