創(chuàng)建線程的多種方式
- 繼承thread類
- 實現(xiàn)Runnable接口
- 實現(xiàn)callable接口
- 使用executor框架實現(xiàn)線程池
線程的狀態(tài)
- 新建狀態(tài)
當一個Thread類或者其子類的對象被聲明或者是創(chuàng)建奕翔,但沒有執(zhí)行的這段狀態(tài)稱為新建狀態(tài)派继。
- 就緒狀態(tài)
就緒狀態(tài)也稱為可運行狀態(tài)互艾。處于新建狀態(tài)的線程被啟動后讯泣,將進入線程列隊排隊等候cpu的調(diào)度,此時具備了運行的條件昨稼,也就是就緒狀態(tài)拳锚。
- 運行狀態(tài)
就緒狀態(tài)的線程獲得cpu的調(diào)度并獲得系統(tǒng)資源后便進入了運行狀態(tài)霍掺。
處于運行狀態(tài)的線程在一下情況下將讓出cpu的控制權(quán)
●線程運行完畢。
●有比當前優(yōu)先級更高的線程處于就緒狀態(tài)牙丽。
●線程主動睡眠一段時間兔魂。
●線程正在等待某一資源。
- 阻塞狀態(tài)
一個運行的線程在某些特殊的情況下將讓出cpu构罗,并暫時中止自己的執(zhí)行遂唧。線程處于這種不可運行的狀態(tài)稱為阻塞狀態(tài)吊奢。下面幾種情況下可以使一個線程進入阻塞狀態(tài)。
●調(diào)用sleep()或者yield()方法谬泌。
●等待一個條件變量線程調(diào)用wait()方法逻谦。
●該線程與另一個線程join()在一起。
一個線程被阻塞時不能進入排隊隊列贱鼻,阻塞的原因被消除時才能進入就緒狀態(tài)邻悬。阻塞狀態(tài)的線程通常需要某些事件才能喚醒随闽,睡眠狀態(tài)的線程必須阻塞一段固定時間。
- 消亡狀態(tài)
處于消亡狀態(tài)的線程不具備繼續(xù)執(zhí)行的能力蛾扇,導(dǎo)致線程消亡的原因有兩個:一是執(zhí)行了run()方法的最后一條語句魏滚,二是進程中的線程被強制終止。
線程的調(diào)度與優(yōu)先級:java語言支持搶占調(diào)度模型更哄,每個線程都被賦予一個執(zhí)行的優(yōu)先級成翩。從1到10整數(shù)型花颗。Thread類有三個優(yōu)先級的靜態(tài)變量MIN_PRIORITY(1),MAX_PRIORITY(10),NORM_PRIORITY(5)。
User Thread(用戶線程) vs Daemon Thread(守護線程)
java中有兩類線程庸论,分別是用戶線程和守護線程只要當前JVM實例中尚存在任何一個非守護線程沒有結(jié)束棒呛,守護線程就全部工作;只有當最后一個非守護線程結(jié)束時鱼喉,守護線程隨著JVM一同結(jié)束工作扛禽。
守護線程的存在主要是為其他線程提供服務(wù),GC(垃圾回收)線程就是一個典例的守護線程豆巨。
用法上兩者并沒有什么區(qū)別掐场,唯一區(qū)別是jvm結(jié)束時的區(qū)別:jvm要等所有用戶線程結(jié)束掉后才會離開,而不用等待守護線程萍膛,守護線程隨著jvm的結(jié)束而結(jié)束(當然守護線程任務(wù)完成后也會結(jié)束)
使用場景
- 消息推送線程
- 資源監(jiān)控等
使用方法
Thread daemonTread = new Thread();
daemonThread.setDaemon(true);
daemonThread.start();
User Thread 和 Daemon Thread 使用注意點
- 守護線程要在
start()
方法調(diào)用之前調(diào)用setDaemon(true)
來把線程設(shè)置為守護線程蝗罗,否者會拋出IllegalThreadStateException異常麦到。 - 守護線程新建的線程默認也是守護線程,當然用戶線程新建的線程默認也是用戶線程拟赊。(主要參考Thread的init方法)
- 用戶線程線程可以創(chuàng)建守護線程粹淋,當然守護線程也可以創(chuàng)建用戶線程桃移。
- 不要把業(yè)務(wù)類的或計算類等重要流程放到守護線程中去,因為在jvm計算時若計算未完成則也會結(jié)束掉守護線程过吻。
- 不要隨便使用用戶線程蔗衡。如在Web容器啟動時啟動Timer,當Web容器關(guān)閉時逼纸,除非你手工關(guān)閉這個Timer济蝉,否則Timer中的任務(wù)還會繼續(xù)運行菠发!