多線程基本知識
多線程面試題
線程基本知識
1.進程與線程的區別?
難2出現3
進程是由指令和數據組成,要運行這些指令,數據讀寫,就要將指令加載到cpu,數據加載到內存。
當一個程序被運行就是開啟了一個進程
一個線程就是一個指令流,將指令流一條一條的交給cpu執行,一個進程可以有多個線程
進程和線程區別:
回答
- 進程是正在運行的程序的實例,進程中包含了線程,每個線程執行不同的任務
- 不同的進程之間使用不同的內存空間,當前進程之間可以共享內存空間
- 線程更加輕量級,線程上下文和切換成本比進程小
2.并行和并發有什么區別
難2出現2
單核cpu
1.在單核cpu下實際上還是串行執行的 先去執行線程1再去執行線程2輪著執行
2.操作系統中有一個組件叫做任務調度器的東西,將cpu的時間片分給不同的程序抵用,由于cpu在線程之間切換快說以人感覺就是一起執行的
3.總結為一句話就是微觀串行,宏觀并行
4.一般將線程輪流使用的做法叫做并發
多核cpu
每個核心都可以調度線程,這個時候線程就是并行
兩個cpu可以同時去執行兩個線程
區別
- 并發是同一時刻應對多件事情的能力
- 并行是同一時間動手做多件事情的能力
舉例子
一個家庭主婦要做飯、打掃、給孩子喂奶、輪流做這事情叫做并發
家庭主婦雇傭了一個保姆,他們一起做這些事情既有并發也有并行
家庭主婦雇傭了三個保姆,一個做飯、一個打掃、一個給孩子喂奶,互不打擾叫做并行
回答
在多核cpu下:
并發是同一時刻應對多件事情的能力,多個線程輪流使用一個或者多個cpu
并行就是同一時間做多件事情的能力,比如4個cpu同時執行4個線程
3.創建線程方式有哪些
難2 出現4
4種創建線程的方式
1.繼承Thread類
先繼承一個Thread接口 重寫方法 然后創建實例對象 調用start方法
2.實現runnable 接口
先實現一個Runnable接口重寫run方法 創建對象 調用start方法
3.實現Callable接口
1.繼承Callable接口重寫call方法可以有泛型 異常 返回值 等等
2.創建接口實例對象
3.創建一個FutureTark<string>對象將接口實例對象復制給他
4.然后創建thread對象將futureTark對象賦值給thread對象
5.調用start方法啟動線程 用futureTark對象.get可以獲得返回值
4.線程池創建線程
繼承thread或者實現runnable創建任務 然后創建線程池對象實例 用線程池對象實例去調用submit方法 將剛剛創建的任務提交 最后關閉線程池
回答
繼承Thread類
實現runnable 接口
實現Callable接口
線程池創建線程 回答追問在說區別
runnable和callable有什么區別
回答
- Runnable接口run方法沒有返回值 run的異常只能在內部消化不能繼續向上拋出
- Callable接口有返回值和FutureTack配合get方法獲取線程的執行結果,有泛型,可以拋出異常
啟動線程可以使用run方法嗎 用run和start有什么區別
回答
可以使用但是run方法使用是在主線程去運行相當于去調用一個普通方法 而start方法是開啟一個線程去異步的運行,不可以開啟多次開啟線程,只能被調用一次
4.線程包含哪些狀態
難3出現4
參考Thread類中的枚舉方法
6種
NEW,RUNNABLE,BLOCKED,WATING,TIMED_WAITNG,TERMINATED
public enum State {
/**
* 尚未啟動的線程的線程狀態。.
*/
NEW,
/**
* 可運行線程的線程狀態。可運行線程中的一個線程
* 狀態在Java虛擬機中執行,但它可能等待來自操作系統的其他資源
*如處理機.
*/
RUNNABLE,
/**
* 等待監視器鎖的線程的線程狀態。
* 處于阻塞狀態的線程正在等待監視器鎖
* 進入同步塊/方法或
* 調用后重新進入同步塊/方法
* {@link Object#wait() Object.wait}。
*/
BLOCKED,
/**
等待線程的線程狀態。 線程處于等待狀態
*/
WAITING,
/**
*指定等待時間的等待線程狀態。線程由于調用其中一個而處于定時等待狀態
*/
TIMED_WAITING,
/**
*終止線程的線程狀態。
*線程已經完成執行。
*/
TERMINATED;
}
當一個線程新建出來就是新建狀態,調用了start()方法之后就變成了可運行狀態,可運行狀態分成了就緒(搶到cpu執行權利之后變成運行)和運行狀態,執行完之后變成死亡狀態,之間有可能加鎖就是沒有執行的權利就進入阻塞狀態,還有可能是調用了wait()方法就變成了等待狀態等待別人調用notify()方法,還有就是調用了sleep(時間)方法就是變成了即使等待狀態,等待時間到
5.新建三個線程怎么保證他們的循序執行
難2出現3
使用線程中的join方法
join()等待線程運行結束 加入冒一個線程 等待那個線程完了之后在調用這個線程
阻塞調用此方法的線程進入即時等待狀態

6.notify()和notiftyAll()有什么區別
難2出現3
- notiftyAll()所有wait()的線程
- noti喚醒一個調用了wait方法的線程
7.java中的wait()和sleep()有什么不同
難3出現3
wait() wait(時間) 到時間之后可以自動喚醒
共同點:都能讓當前線程暫時放棄cpu的使用權,進入阻塞狀態
不同點:
1.方法的歸屬不同
-
sleep屬于Thread的靜態方法
-
wait(),wait(long)屬于object的方法每個對象都默認有
2.醒來的時機不一樣
-
帶參數的到時間之后都可以被自動的喚醒
-
wait(),wait(long)還可以被notify喚醒,wait()如果不喚醒就會一直等下去
-
他們都可被打斷喚醒
3.鎖特性不同
-
wait()必須配合鎖對象使用 先獲取鎖對象,而sleep不用
-
wait執行完后之后會釋放鎖對象,其他線程可以調用。sleep方法在鎖中執行不會釋放對象 一個是放棄cpu使用權其他人可以用一個是啊放棄之后你們也不能用

8.怎么停止一個正在運行的線程
難2出現3
3種方式退出線程
1.新建一個退出標記 正常的退出線程


2.使用stop方法強制終止,已經作廢(不推薦使用)
3.使用interrupt方法中斷線程,
- 打斷阻塞的線程的線程會拋出打斷異常
- 打斷正常的線程,可以更具打斷狀態來標記是否退出線程和第一種差不多
本文基于黑馬程序員的面試篇b站

浙公網安備 33010602011771號