详解java中Thread类,线程和进程的基本区别,多线程的好处,线程的五个生命周期,主线程和IDEA创建的Monitor Ctrl-Break守护线程;优雅地终止线程。死锁的产生
線程:CPU調(diào)度的最小單位;線程共享堆內(nèi)存和方法區(qū),但各自享有棧空間。進(jìn)程:CPU分配資源的最小單位。
為什么需要多線程:①避免其中一個模塊阻塞造成系統(tǒng)假死;②程序異步處理(交替執(zhí)行),提高程序執(zhí)行效率。
1. 創(chuàng)建線程
1.1 創(chuàng)建線程主要有三種方式,第一種就是創(chuàng)建一個類,該類繼承Thread類并覆蓋Thread類的run方法。
1.2 啟動線程及運(yùn)行結(jié)果
1.3?創(chuàng)建線程的第二種方式,就是調(diào)用Thread構(gòu)造方法時傳入Runnable接口的實現(xiàn)類對象,Runnable接口實現(xiàn)類定義如下。
1.4?啟動線程及運(yùn)行結(jié)果
1.5 創(chuàng)建線程的第三種方式,創(chuàng)建一個Callable接口的實現(xiàn)類,然后將該實現(xiàn)類對象作為參數(shù)放入FutureTask類的構(gòu)造方法中,最終將FutureTask對象作為參數(shù)放入Thread類的構(gòu)造方法中,敘述有點繁瑣,代碼如下。
1.6 啟動線程及運(yùn)行結(jié)果
1.7 雖然FutureTask類的對象可以作為Thread構(gòu)造方法參數(shù),但是我們發(fā)現(xiàn)Thread的構(gòu)造方法中,并沒有FutureTask類對象作為參數(shù)的構(gòu)造方法,如下圖。
那我們看看FutureTask源碼,如下圖,FutureTask實現(xiàn)了RunnableFuture接口。
而RunnableFuture接口繼承了Runnable接口并繼承了run()方法。
1.8 所以,雖然有三種方式實現(xiàn)線程,但是最終實現(xiàn)線程的本質(zhì)就只是兩種方式,一種是繼承Thread類,另一種就是Runnable接口的實現(xiàn)類對象。一般使用第二種方式實現(xiàn)線程,因為一個類如果直接繼承Thread類,那么就無法繼承其它類了;而一個類如果實現(xiàn)Runnable接口,仍然可以繼承其它類或?qū)崿F(xiàn)其它接口,更靈活。但是實現(xiàn)Runnable接口的類,有時候不是很方便。比如Runnable? r = new MyRunnable(); Thread t = new Thread(r);此時我們是無法提供線程對象 t 得到Runnable實現(xiàn)類對象 r 的。
1.9 創(chuàng)建線程的匿名內(nèi)部類形式,如下圖。
2. 線程的五個生命周期
new了一個線程對象,則進(jìn)入新建狀態(tài);執(zhí)行start()方法后,進(jìn)入可運(yùn)行狀態(tài)(又稱就緒狀態(tài)),表示當(dāng)前線程具有搶奪cpu時間片的能力,當(dāng)線程搶奪到CPU時間片,會執(zhí)行run方法;run方法的執(zhí)行標(biāo)志著線程進(jìn)入運(yùn)行狀態(tài),當(dāng)之前占有的CPU時間片用完后,會重新回到就緒狀態(tài)搶奪CPU時間片,run方法執(zhí)行結(jié)束則進(jìn)入死亡狀態(tài);如果遇到阻塞事件(如接收用戶輸入,sleep方法,join方法),則進(jìn)入阻塞狀態(tài)。干講還是有點繁瑣,下面通過一幅圖來整理說明。
3. 主線程
3.1 我們java程序一啟動,JVM就會創(chuàng)建一個主線程。下圖顯示兩個線程,它們是main主線程(去執(zhí)行main方法)和Monitor Ctrl-Break后臺監(jiān)控線程(IDEA開發(fā)環(huán)境創(chuàng)建的一個線程),后臺線程可通過setDaemon(true)來設(shè)定,如網(wǎng)絡(luò)連接(主線程)和心跳包發(fā)送(守護(hù)線程,主線程斷開連接,那么不需要再發(fā)送心跳包)。
3.2 如果分支線程有main方法,會不會變?yōu)橹骶€程?測試代碼和運(yùn)行結(jié)果及分析如下圖。
public class ThreadMainTest {public static void main(String[] args){MyThread mt = new MyThread();mt.start();for (int i = 0; i < 10; i++) {System.out.println("主線程: " + i);}} } class MyThread extends Thread{public static void main(String[] args) {for (int i = 0; i < 10; i++) {System.out.println(" 分支線程的main方法: " + i);}}@Overridepublic void run() {main(new String[]{});for (int i = 0; i < 10; i++) {System.out.println(super.getName() + " 分支線程的run方法: " + i);}} }4. 終止線程
4.1 第一種,通過設(shè)定一個布爾型的標(biāo)志位成員變量,來決定是否結(jié)束線程,如下圖。
4.2 自己設(shè)定一個異常,當(dāng)發(fā)生異常時,結(jié)束線程,這邊以InterruptedException為例,如下圖。
5. 死鎖
5.1 死鎖怎么產(chǎn)生的?多個線程互相等待對方資源,得到資源前,不會釋放自己已有的資源,出現(xiàn)了循環(huán)等待的現(xiàn)象。
5.2 怎么避免死鎖?①系統(tǒng)安全狀態(tài)判斷法:在分配系統(tǒng)資源前,判斷此次資源分配的安全性。②銀行家算法:不也是通過系統(tǒng)安全判定算法來實現(xiàn)嗎?當(dāng)系統(tǒng)剩余的資源滿足所需求的資源,說明已分配的資源可以收回來。
5.3 發(fā)生死鎖怎么處理?①操作系統(tǒng)將該線程掛起,并搶占該線程資源;②操作系統(tǒng)強(qiáng)制撤銷線程并剝奪資源;③線程回退,將線程回退至系統(tǒng)安全狀態(tài)。
總結(jié)
以上是生活随笔為你收集整理的详解java中Thread类,线程和进程的基本区别,多线程的好处,线程的五个生命周期,主线程和IDEA创建的Monitor Ctrl-Break守护线程;优雅地终止线程。死锁的产生的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: IO流介绍、java常用的几个IO流类之
- 下一篇: 单线程下的生产者--消费者模式详解,wa