[19/04/07-星期日] 多线程_线程的状态(新生、就绪、运行、死亡)
一、概念
? ? ? 一個線程對象在它的生命周期內,需要經歷5個狀態。
?
? 新生狀態(New)
? ? ??用new關鍵字建立一個線程對象后,該線程對象就處于新生狀態。處于新生狀態的線程有自己的內存空間,通過調用start方法進入就緒狀態。
??就緒狀態(Runnable)
? ? ??處于就緒狀態的線程已經具備了運行條件,但是還沒有被分配到CPU,處于“線程就緒隊列”,等待系統為其分配CPU。就緒狀態并不是執行狀態,
當系統選定一個等待執行的Thread對象后,它就會進入執行狀態。一旦獲得CPU,線程就進入運行狀態并自動調用自己的run方法。
有4個原因會導致線程進入就緒狀態:
? ? ??1. 新建線程:調用start()方法,進入就緒狀態;
? ? ??2. 阻塞線程:阻塞解除,進入就緒狀態;
? ? ??3. 運行線程:調用yield()方法,直接進入就緒狀態;
? ? ??4. 運行線程:JVM將CPU資源從本線程切換到其他線程。
【yield()方法】
/**就緒狀態(Runnable) yield 放棄,屈服* 2-3、運行線程:調用yield()方法,直接進入就緒狀態; yield 禮讓(cpu的調度給別的)線程,暫停線程* 讓當前正在執行的線程暫停不是阻塞線程,而是將線程從運行狀態轉入就緒狀態;讓cpu重新調度 ** */ package cn.sxt.thread;public class Test_0407_ThreadRunnable_yield {static class Test_yield implements Runnable{//線程入口入口點public void run() {for (int i = 1; i <100; i++) {System.out.println("靜態內部類線程-->>"+i);} } } public static void main(String[] args) {new Thread(new Test_yield()).start();for (int i = 1; i <= 100; i++) {if (i%5==0) { //是5的倍數,主方法線程禮讓一次 .有的時候禮讓并不一定成功 Thread.yield(); }System.out.println("主方法線程-->>"+i); }} }?
??運行狀態(Running)
? ? ??在運行狀態的線程執行自己run方法中的代碼,直到調用其他方法而終止或等待某資源而阻塞或完成任務而死亡。如果在給定的時間片內沒有執行結束,
就會被系統給換下來回到就緒狀態。也可能由于某些“導致阻塞的事件”而進入阻塞狀態。
??阻塞狀態(Blocked)
? ? ??阻塞指的是暫停一個線程的執行以等待某個條件發生(如某資源就緒)。有4種原因會導致阻塞:
? ? ??1. 執行sleep(int millsecond)方法,使當前線程休眠,進入阻塞狀態。當指定的時間到了后,線程進入就緒狀態。抱著資源睡覺不給別人用。
? ? ??2. 執行wait()方法,使當前線程進入阻塞狀態。當使用nofity()方法喚醒這個線程后,它進入就緒狀態。等著別人用完資源。
? ? ??3. 線程運行時,某個操作進入阻塞狀態,比如執行IO流操作(read()/write()方法本身就是阻塞的方法)。只有當引起該操作阻塞的原因消失后,線程進入就緒狀態。
? ? ??4. join()線程聯合: 當某個線程等待另一個線程執行結束后,才能繼續執行時,使用join()方法。有人插隊。
【sleep()方法】
/***線程阻塞狀態* 3-1:sleep() 方法 。抱著資源睡覺。模擬網絡延時,放大發生問題的可能性,便于解決問題如12306,有數據錯誤* 龜兔賽跑,模擬兔子睡覺 ;可以寫倒計時* * */ package cn.sxt.thread;import java.text.SimpleDateFormat; import java.util.Date;public class Test_0407_ThreadBlocked_sleep {public static void main(String[] args) throws InterruptedException {/*//倒數10個數 1秒鐘一個數。這里是死循環。哪里寫sleep哪個線程就睡覺,進行阻塞,這里寫在主方法里int num=10;while (true) {Thread.sleep(1000); //主方法線程要阻塞System.out.println(num--);} *///倒計時 endDate對象的初始值是當前時間加10秒后,從下文看是個變量Date endDate=new Date(System.currentTimeMillis()+1000*10); //電腦系統當前時間+10秒=最終電腦系統線要終止的時刻System.out.println(new SimpleDateFormat("yy:mm:ss").format(System.currentTimeMillis())+"---->");long end=endDate.getTime();//end是個定值表示10秒后的時刻System.out.println(new SimpleDateFormat("yy:mm:ss").format(end)+"---->");while (true) {System.out.println(new SimpleDateFormat("yy:mm:ss").format(endDate));//格式化打印時間Thread.sleep(1000);//getTime()得到對象的時間endDate=new Date(endDate.getTime()-1000);//10秒后的時間開始自減直到減到當前時間if (end-10000>endDate.getTime()) { //endDate.getTime()一直在變小,當小于臨界值系統當前的時刻時,跳出循環break; } }} }【join()方法】
/** 3-4 join()線程聯合: 當某個線程等待另一個線程執行結束后,才能繼續執行時,使用join()方法。有人插隊。 *其它線程必須讓新插入的線程執行完畢才能繼續執行。 * *線程A在運行期間,可以調用線程B的join()方法,讓線程B和線程A聯合。這樣,線程A就必須等待線程B執行完畢后,才能繼續執行。 *如下面示例中,“爸爸線程”要抽煙,于是聯合了“兒子線程”去買煙,必須等待“兒子線程”買煙完畢,“爸爸線程”才能繼續抽煙。* */ package cn.sxt.thread;public class Test_0407_ThreadBlocked_join {public static void main(String[] args) {System.out.println("爸爸和兒子買煙故事");/*Thread father = new Thread(new FatherThread());father.start();*/new Thread(new FatherThread()).start();} } class FatherThread implements Runnable {public void run() {System.out.println("爸爸想抽煙,發現煙抽完了");System.out.println("爸爸讓兒子去買包紅塔山");//父親線程中新插入兒子的線程Thread son = new Thread(new SonThread());son.start();System.out.println("爸爸等兒子買煙回來");try {son.join();//join寫在父親線程中,所以父親線程被阻塞,必須等兒子線程執行完他才開始執行} catch (InterruptedException e) {e.printStackTrace();System.out.println("爸爸出門去找兒子跑哪去了");// 結束JVM。如果是0則表示正常結束;如果是非0則表示非正常結束System.exit(1);}System.out.println("爸爸高興的接過煙開始抽,并把剩下的零錢給了兒子");} }class SonThread implements Runnable {public void run() {System.out.println("兒子出門去買煙");System.out.println("兒子買煙需要10分鐘");try {for (int i = 1; i <= 10; i++) {System.out.println("第" + i + "分鐘");Thread.sleep(1000);}} catch (InterruptedException e) {e.printStackTrace();}System.out.println("兒子買煙回來了");} }?
??死亡狀態(Terminated)
? ? ?死亡狀態是線程生命周期中的最后一個階段。線程死亡的原因有兩個。一個是正常運行的線程完成了它run()方法內的全部工作; 另一個是線程被強制終止,
如通過執行stop()或destroy()方法來終止一個線程(注:stop()/destroy()方法已經被JDK廢棄,不推薦使用)。
? ? ?當一個線程進入死亡狀態以后,就不能再回到其它狀態了。
? ? ?終止線程我們一般不使用JDK提供的stop()/destroy()方法(它們本身也被JDK廢棄了)。通常的做法是提供一個boolean型的終止變量,
當這個變量置為false,則終止線程的運行。
/**** 終止線程2種方式:* 1、線程正常執行完畢->線程有次數的限制* 2、外部終止 加入標志位*/ package cn.sxt.thread;import java.util.jar.Attributes.Name;public class Test_0407_ThreadStop implements Runnable {private boolean flag =true;//1、設置線程標志位private String name;public Test_0407_ThreadStop(String name) {//構造器super();this.name = name;}public void run() {//2、關聯標志位 true:線程繼續運行 false:線程終止int i=0;while (flag) {System.out.println(name+"->>"+(i++));} }//3、對外提供標識去改變標識public void stop() {this.flag=false; }public static void main(String[] args) {Test_0407_ThreadStop tt=new Test_0407_ThreadStop("C羅");new Thread(tt).start();//new一個對象進入? 新生狀態 ;通過start()方法進去就緒狀態;cpu調度到了,進入運行狀態(人為不能干預)for (int i = 0; i < 10; i++) {if (i==8) {tt.stop();//線程的終止,死亡狀態System.out.println("比賽結束");}System.out.println("主方法-->>"+i);}}}二、獲取線程基本信息
【代碼】
/** *線程的一些方法* */ package cn.sxt.thread;public class Test_0407_ThreadStates {public static void main(String[] args) throws Exception {System.out.println(Thread.currentThread().isAlive());MyThread myThread = new MyThread("戰斗機");//真實類 ,角色對象,名字通過面向對象思維設置Thread t=new Thread(myThread);//代理類,代理對象t.setName("公雞");//默認代理Thread類t對象的名字是Thread-0,1,2,3..... t.start();Thread.sleep(500);System.out.println(t.isAlive());//判斷線程還在運行嗎? 延時500毫秒,顯然線程已經死亡,輸出false/* Thread t = new Thread(r, "C羅");//定義線程對象,并傳入參數;t.start();//啟動線程;System.out.println("name is: " + t.getName());//輸出線程名稱;System.out.println(t.getPriority());//獲得線程的優先級t.sleep(5000);//Thread.currentThread().sleep(5000);//當前線程暫停5秒; */ } } //設置名字:代理角色(jar包中的Thread類)的名字+代理角色(jar包中的Thread類)的名字 class MyThread implements Runnable {private String name;public MyThread(String name) {super();this.name = name;}//線程體;public void run() {//輸出代理角色(jar包中的Thread類)的名字+代理角色(jar包中的Thread類)的名字System.out.println(Thread.currentThread().getName()+"-->"+name);}}?
轉載于:https://www.cnblogs.com/ID-qingxin/p/10668220.html
總結
以上是生活随笔為你收集整理的[19/04/07-星期日] 多线程_线程的状态(新生、就绪、运行、死亡)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 安逸花可以提前还款吗 产品特点也可以了解
- 下一篇: 坚持c++,真正掌握c++(4)