何為線程?
線程與進程相似,但線程是一個比進程更小的執(zhí)行單位。一個進程在其執(zhí)行的過程中可以產(chǎn)生多個線程。與進程不同的是同類的多個線程共享進程的堆和方法區(qū)資源,但每個線程有自己的程序計數(shù)器、虛擬機棧和本地方法棧,所以系統(tǒng)在產(chǎn)生一個線程,或是在各個線程之間作切換工作時,負擔要比進程小得多,也正因為如此,線程也被稱為輕量級進程。
Java程序天生就是多線程程序,我們可以通過JMX來看一下一個普通的Java程序有哪些線程,代碼如下。
public class MultiThread { public static void main(String[] args) { // 獲取 Java 線程管理 MXBean ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean(); // 不需要獲取同步的 monitor 和 synchronizer 信息,僅獲取線程和線程堆棧信息 ThreadInfo[] threadInfos = threadMXBean.dumpAllThreads(false, false); // 遍歷線程信息,僅打印線程 ID 和線程名稱信息 for (ThreadInfo threadInfo : threadInfos) { System.out.println("[" + threadInfo.getThreadId() + "] " + threadInfo.getThreadName()); } }}
上述程序輸出如下(輸出內(nèi)容可能不同,不用太糾結(jié)下面每個線程的作用,只用知道 main 線程執(zhí)行 main 方法即可):
[5] Attach Listener //添加事件
[4] Signal Dispatcher // 分發(fā)處理給 JVM 信號的線程
[3] Finalizer //調(diào)用對象 finalize 方法的線程
[2] Reference Handler //清除 reference 線程
[1] main //main 線程,程序入口
從上面的輸出內(nèi)容可以看出:一個 Java 程序的運行是 main 線程和多個其他線程同時運行。
程序計數(shù)器為什么是私有的?
程序計數(shù)器主要有下面兩個作用:
字節(jié)碼解釋器通過改變程序計數(shù)器來依次讀取指令,從而實現(xiàn)代碼的流程控制,如:順序執(zhí)行、選擇、循環(huán)、異常處理。
在多線程的情況下,程序計數(shù)器用于記錄當前線程執(zhí)行的位置,從而當線程被切換回來的時候能夠知道該線程上次運行到哪兒了。
需要注意的是,如果執(zhí)行的是native方法,那么程序計數(shù)器記錄的是undefined地址,只有執(zhí)行的是Java代碼時程序計數(shù)器記錄的才是下一條指令的地址。
所以,程序計數(shù)器私有主要是為了線程切換后能恢復到正確的執(zhí)行位置。
虛擬機棧和本地方法棧為什么是私有的?
**虛擬機棧:**每個Java方法在執(zhí)行的同時會創(chuàng)建一個棧幀用于存儲局部變量表、操作數(shù)棧、常量池引用等信息。從方法調(diào)用直至執(zhí)行完成的過程,就對應著一個棧幀在Java虛擬機棧中入棧和出棧的過程。
**本地方法棧:**和虛擬機棧所發(fā)揮的作用非常相似,區(qū)別是:虛擬機棧為虛擬機執(zhí)行Java方法(也就是字節(jié)碼)服務(wù),而本地方法棧則為虛擬機使用到的Native方法服務(wù)。在HotSpot虛擬機中和Java虛擬機棧合二為一。
所以,為了保證線程中的局部變量不被別的線程訪問到,虛擬機棧和本地方法棧是線程私有的。
說說并發(fā)與并行的區(qū)別?
并發(fā):同一時間段,多個任務(wù)都在執(zhí)行(單位時間內(nèi)不一定同時執(zhí)行);
并行:單位時間內(nèi),多個任務(wù)同時執(zhí)行。
為什么要使用多線程呢?
先從總體上來說:
從計算機底層來說:線程可以比作是輕量級的進程,是程序執(zhí)行的最小單位,線程間的切換和調(diào)度的成本遠遠小于進程。另外,多核CPU時代意味著多個線程可以同時運行,這減少了線程上下文切換的開銷。
從當代互聯(lián)網(wǎng)發(fā)展趨勢來說:現(xiàn)在的系統(tǒng)動不動就要求百萬級甚至千萬級的并發(fā)量,而多線程并發(fā)編程正是開發(fā)高并發(fā)系統(tǒng)的基礎(chǔ),利用好多線程機制可以大大提高系統(tǒng)整體的并發(fā)能力以及性能。
再深入到計算機底層來探討:
單核時代:在單核時代多線程主要是為了提高CPU和IO設(shè)備的綜合利用率。舉個例子:當只有一個線程的時候會導致CPU計算時,IO設(shè)備空閑;進行IO操作時,CPU空閑。我們可以簡單地說這兩者的利用率目前都是50%左右。但是當有兩個線程的時候就不一樣了,當一個線程執(zhí)行CPU計算時,另外一個線程可以進行IO操作,這樣兩個的利用率就可以在理想情況下達到100%了。
多核時代:多核時代多線程主要是為了提高CPU利用率。舉個例子:假如我們要計算一個復雜的任務(wù),我們只用一個線程的話,CPU只會一個CPU核心被利用到,而創(chuàng)建多個線程就可以讓多個CPU核心被利用到,這樣就提高了CPU的利用率。
以上就是天津卓眾教育java培訓機構(gòu)的小編針對“Java并發(fā)基礎(chǔ)常見面試題總結(jié)”的內(nèi)容進行的回答,希望對大家有所幫助,如有疑問,請在線咨詢,有專業(yè)老師隨時為你服務(wù)。