1.什麼是進程?

是一個具有一定獨立功能的程序在一個數據集上的一次動態執行的過程,是操作系統進行資源分配和調度的一個獨立單位,是應用程序運行的載體。

2.什麼是線程?

線程是操作系統能夠進行運算調度的最小單位。

它被包含在進程之中,是進程中的實際運作單位。

一條線程指的是進程中一個單一順序的控制流,一個進程中可以並發多個線程,每條線程並行執行不同的任務。

3.進程和線程的區別?

進程和線程的主要差別在於它們是不同的操作系統資源管理方式。

進程有獨立的地址空間,一個進程崩潰後,在保護模式下不會對其它進程產生影響。

線程只是一個進程中的不同執行路徑。線程有自己的堆棧和局部變數,但線程之間沒有單獨的地址空間,一個線程死掉就等於整個進程死掉,所以多進程的程序要比多線程

的程序健壯,但在進程切換時,耗費資源較大,效率要差一些。

但對於一些要求同時進行並且又要共享某些變數的並發操作,只能用線程,不能用進程。

4.多線程和單線程有什麼區別?

單線程程序:程序執行過程中只有一個有效操作的序列,不同操作之間都有明確的執行先後順序,容易出現代碼阻塞

多線程程序:有多個線程,線程間獨立運行,能有效地避免代碼阻塞,並且提高程序的運行性能

5.為什麼要使用多線程?

(1)使用多線程可以減少程序的響應時間。 在單線程的情況下,如果某個程序很耗時或者陷入長時間等待(如等待網路響應),此時程序將不會相應滑鼠和鍵盤等操作,使用多線程後,可以把這個耗時的線程分配到一個單獨的線程去執行,從而是程序具備了更好的交互性。

(2)與進程相比,線程的創建和切換開銷更小。 由於啟動一個新的線程必須給這個線程分配獨立的地址空間,建立許多數據結構來維護線程代碼段、數據段等信息,而運行於同一個進程內的線程共享代碼段、數據段,線程的啟動或切換的開銷就比進程要少很多。同時多線程在數據共享方面效率非常高。

(3)多CPU或多核心計算機本身就具有執行多線程的能力。 如果使用單個線程,將無法重複利用計算機資源,造成資源的巨大浪費。因此在多CPU計算機上使用多線程能提高CPU的利用率。

(4)使用多線程能簡化程序的結構,使用程序便於理解和維護。 一個非常複雜的進程可以分成多個線程來執行。

6.什麼是線程安全?

當多個線程訪問同一個對象時,如果不用考慮這些線程在運行時環境下的調度和交替運行,也不需要進行額外的同步,或者在調用方進行任何其他的協調操作,調用這個對象的行為都可以獲取正確的結果,那這個對象是線程安全的。 ——<<深入Java虛擬機>>

7.為何要使用線程同步?

Java允許多線程並發控制,當多個線程同時操作一個可共享的資源變數時(如數據的增刪改查),將會導致數據不準確,相互之間產生衝突。

因此加入同步鎖以避免在該線程沒有完成操作之前,被其他線程的調用,從而保證了該變數的唯一性和準確性。

8.如何確保線程安全?

  • 對非安全的代碼進行加鎖控制
  • 使用線程安全的類
  • 多線程並發情況下,線程共享的變數改為方法級的局部變數

9.什麼是原子操作?

檢查數值、改變數值,以及可能發生的睡眠操作均作為單一的、不可分割的原子操作完成。

10Java內存模型是什麼?

  1. Java中所有變數都儲存在主存中,對於所有線程都是共享的(因為在同一進程中),每個線程都有自己的工作內存或本地內存(Working Memory),工作內存中保存的是主存中某些變數的拷貝,線程對所有變數的操作都是在工作內存中進行,而線程之間無法相互直接訪問,變數傳遞均需要通過主存完成,但是在程序內部可以互相調用(通過對象方法),所有線程間的通信相對簡單,速度也很快。

2、進程間的內部數據和狀態都是相互完全獨立的,因此進程間通信大多數情況是必須通過網路實現。線程本身的數據,通常只有寄存器數據,以及一個程序執行時使用的堆棧,所以線程的切換比進程切換的負擔要小。

3、CPU對於各個線程的調度是隨機的(分時調度),在Java程序中,JVM負責線程的調度。 線程調度是指按照特定的機製為多個線程分配CPU的使用權,也就是實際執行的時候是線程,因此CPU調度的最小單位是線程,而資源分配的最小單位是進程。

11.Java中堆和棧有什麼不同?

棧:在函數中定義的基本類型的變數和對象的引用變數都是在函數的棧內存中分配。

堆:堆內存用於存放由new創建的對象和數組。

從通俗化的角度來說,堆是用來存放對象的,棧是用來存放執行程序的

12.JVM中哪個參數是用來控制線程的棧堆棧小的

-Xss參數用來控制線程的堆棧大小。

13.什麼是競態條件?你怎樣發現和解決競爭?

當兩個線程競爭同一資源時,如果對資源的訪問順序敏感,就稱存在競態條件。

在臨界區中使用適當的同步就可以避免競態條件。

界區實現方法有兩種,一種是用synchronized,一種是用Lock顯式鎖實現。

14.線程安全的級別

不可變

不可變的對象一定是線程安全的,並且永遠也不需要額外的同步。

Java類庫中大多數基本數值類如Integer、String和BigInteger都是不可變的。

15.無條件的線程安全

由類的規格說明所規定的約束在對象被多個線程訪問時仍然有效,不管運行時環境如何排列,線程都不需要任何額外的同步。

如 Random 、ConcurrentHashMap、Concurrent集合、atomic

16有條件的線程安全

有條件的線程安全類對於單獨的操作可以是線程安全的,但是某些操作序列可能需要外部同步。

有條件線程安全的最常見的例子是遍歷由 Hashtable 或者 Vector 或者返回的迭代器

17.非線程安全(線程兼容)

線程兼容類不是線程安全的,但是可以通過正確使用同步而在並發環境中安全地使用。

如ArrayList HashMap

18.線程對立

線程對立是那些不管是否採用了同步措施,都不能在多線程環境中並發使用的代碼。

如如System.setOut()、System.runFinalizersOnExit()

19.你對線程優先順序的理解是什麼?

每一個線程都是有優先順序的,一般來說,高優先順序的線程在運行時會具有優先權,但這依賴於線程調度的實現,這個實現是和操作系統相關的(OSdependent)。

可以定義線程的優先順序,但是這並不能保證高優先順序的線程會在低優先順序的線程前執行。線程優先順序是一個int變數(從1-10),1代表最低優先順序,10代表最高優先順序。

20.什麼是線程調度器(Thread Scheduler)和時間分片(Time Slicing)?

線程調度器是一個操作系統服務,它負責為Runnable狀態的線程分配CPU時間。一旦創建一個線程並啟動它,它的執行便依賴於線程調度器的實現。

時間分片是指將可用的CPU時間分配給可用的Runnable線程的過程。分配CPU時間可以基於線程優先順序或者線程等待的時間。

線程調度並不受到Java虛擬機控制,所以由應用程序來控制它是更好的選擇。

21.在多線程中,什麼是上下文切換(context-switching)?

單核CPU也支持多線程執行代碼,CPU通過給每個線程分配CPU時間片來實現這個機制。時間片是CPU分配給各個線程的時間,因為時間片非常短,所以CPU通過不停地切換線程執行,讓我們感覺多個線程時同時執行的,時間片一般是幾十毫秒(ms)。

操作系統中,CPU時間分片切換到另一個就緒的線程,則需要保存當前線程的運行的位置,同時需要載入需要恢複線程的環境信息。

22.用戶線程和守護線程有什麼區別?

守護線程都是為JVM中所有非守護線程的運行提供便利服務: 只要當前JVM實例中尚存在任何一個非守護線程沒有結束,守護線程就全部工作;只有當最後一個非守護線程結束時,守護線程隨著JVM一同結束工作。

User和Daemon兩者幾乎沒有區別,唯一的不同之處就在於虛擬機的離開:如果 User Thread已經全部退出運行了,只剩下Daemon Thread存在了,虛擬機也就退出了。

因為沒有了被守護者,Daemon也就沒有工作可做了,也就沒有繼續運行程序的必要了。

23.如何創建守護線程?以及在什麼場合來使用它?

任何線程都可以設置為守護線程和用戶線程,通過方法Thread.setDaemon(bool on);true則把該線程設置為守護線程,反之則為用戶線程。Thread.setDaemon()必須在Thread.start()之前調用,否則運行時會拋出異常。

守護線程相當於後台管理者 比如 : 進行內存回收,垃圾清理等工作

24.線程的狀態轉換?

1、新建狀態(New):新創建了一個線程對象。

2、就緒狀態(Runnable):線程對象創建後,其他線程調用了該對象的start()方法。該狀態的線程位於可運行線程池中,變得可運行,等待獲取CPU的使用權。

3、運行狀態(Running):就緒狀態的線程獲取了CPU,執行程序代碼。

4、阻塞狀態(Blocked):阻塞狀態是線程因為某種原因放棄CPU使用權,暫時停止運行。直到線程進入就緒狀態,才有機會轉到運行狀態。阻塞的情況分三種: (一)、等待阻塞:運行的線程執行wait()方法,JVM會把該線程放入等待池中。(wait會釋放持有的鎖) (二)、同步阻塞:運行的線程在獲取對象的同步鎖時,若該同步鎖被別的線程佔用,則JVM會把該線程放入鎖池中。 (三)、其他阻塞:運行的線程執行sleep()或join()方法,或者發出了I/O請求時,JVM會把該線程置為阻塞狀態。當sleep()狀態超時、join()等待線程終止或者超時、或者I/O處理完畢時,線程重新轉入就緒狀態。(注意,sleep是不會釋放持有的鎖)

5、死亡狀態(Dead):線程執行完了或者因異常退出了run()方法,該線程結束生命周期。

25.線程中斷是否能直接調用stop,為什麼?

Java提供的終止方法只有一個stop,但是不建議使用此方法,因為它有以下三個問題:

  1. stop方法是過時的 從Java編碼規則來說,已經過時的方式不建議採用.
  2. stop方法會導致代碼邏輯不完整 stop方法是一種」惡意」的中斷,一旦執行stop方法,即終止當前正在運行的線程,不管線程邏輯是否完整,這是非常危險的.

原文:Java架構筆記

免費Java高級資料需要自己領取,涵蓋了Java、Redis、MongoDB、MySQL、Zookeeper、Spring Cloud、Dubbo高並發分散式等教程,一共30G。

傳送門: https://mp.weixin.qq.com/s/JzddfH-7yNudmkjT0IRL8Q

推薦閱讀:

相关文章