高併發面試總結

  1. 什麼是進程

進程是指運行中的應用程序,每一個進程都有本身獨立的地址空間(內存空間)。 好比用戶點擊桌面的IE瀏覽器,就啓動了一個進程,操做系統就會爲該進程分配獨立的地址空間。當用戶再次點擊左邊的IE瀏覽器,又啓動了一個進程,操做系統將爲新的進程分配新的獨立的地址空間。目前操做系統都支持多進程。java

  1. 什麼是線程

進程是表示自願分配的基本單位。而線程則是進程中執行運算的最小單位,即執行處理機調度的基本單位。通俗來說:一個程序有一個進程,而一個進程能夠有多個線程。程序員

  1. 多線程的幾種實現方式

(1) 繼承Thread類建立線程面試

Thread類本質上是實現了Runnable接口的一個實例,表明一個線程的實例。啓動線程的惟一方法就是經過Thread類的start()實例方法。start()方法將啓動一個新線程,並執行run()方法。這種方式實現多線程比較簡單,經過本身的類直接繼承Thread,並重寫run()方法,就能夠啓動新線程並執行本身定義的run()方法。算法

(2) 實現Runnable接口建立線程數據庫

若是本身的類已經繼承了兩一個類,就沒法再繼承Thread,所以能夠實現一個Runnable接口 (3) 實現Callable接口經過FutureTask包裝器來建立Thread線程編程

(4) 使用ExecutorService、Callable、Future實現有返回結果的線程數組

ExecutorService、Callable、Future三個接口實際上都是屬於Executor框架。返回結果的線程是在JDK1.5中引入的新特徵,有了這種特徵就不須要再爲了獲得返回值而大費周折了。 可返回值的任務必須實現Callable接口;無返回值的任務必須實現Runnabel接口。 執行Callable任務後,能夠獲取一個Future對象,在該對象上調用get()方法就能夠獲取到Callable任務返回的Object了。(get()方法是阻塞的,線程無返回結果,該方法就一直等待)瀏覽器

  1. Vector、SimpleDateFormat是線程安全類嗎

Vector類的單個方法是原子性的,符合操做不是原子性的 SimpleDateFormat類不是線程安全的緩存

  1. 哪些集合類是線程安全的

1.Vector 2.Stack 3.hashtable 4.enumeration 5.StringBuffer安全

  1. 多線程中忙循環是什麼

忙循環就是程序員用循環讓一個線程等待,不像傳統方法wait()、sleep()或者yied()它們都放棄了CPU控制,而忙循環不會放棄CPU,它就是在運行一個空循環。這麼作的目的是爲了保留CPU緩存,在多核系統中,一個等待線程醒來的時候可能會在另外一個內核運行,這樣會重建緩存。爲了不重建緩存和減小等待重建的時間就可使用它了。

  1. 什麼是線程局部變量

ThreadLocal並不是是一個線程本地實現版本,它並非一個Thread,而是threadlocalvariable(線程局部變量)。也許把它命名爲ThreadLocalVar更合適。線程局部變量(ThreadLocal)功能很是簡單,就是爲每個使用該變量的線程都提供了一個變量值副本,是java中一種較爲特殊的線程綁定機制,是每個線程均可以獨立地改變本身的副本,而不會和其餘線程的副本衝突。

  1. 進程間如何通信

管道(pipe)

管道是一種半雙工的通訊方式,數據只能單向流動,並且只能在具備親緣關係的進程間使用。進程的親緣關係一般是指父子進程關係 有名管道(namedpipe)

有名管道也是半雙工的通訊方式,可是它云溪無親緣關係進程間的通訊。 信號量(semaphore)

信號量是一個計數器,能夠用來控制多個進程對共享資源的訪問。它常做爲一種鎖機制,防止某進程正在訪問共享資源時,其餘進程也訪問該資源。所以,主要做爲進程間以及同一進程內不一樣線程之間的同步手段。 消息隊列(messagequeue)

消息隊列裏有消息的鏈表,存放在內核中並由消息隊列標識符標識。消息隊列克服了信號傳遞消息少、管道只能承載無格式字節流以及緩衝區大小受限等缺點 信號(signal)

信號是一種比較複雜的通訊方式,用於通知接收進程某個事件已經發生 共享內存(shared memory)

共享內存就是映射一段能被其餘進程所訪問的內存,這段共享內存由一個進程建立,但多個進程均可以訪問。共享內存是最快的IPC方式,它是針對其餘進程間通訊方式運行效率低而專門設計的。它每每與其餘通訊機制,如信號量配合使用,來實現進程間的同步和通訊。 套接字(socket)

套接口也是一種進程間通訊機制,以其餘通訊機制不一樣的是,它可用於不一樣進程間的通訊

  1. 線程間如何通信

鎖機制:包括互斥鎖、條件變量、讀寫鎖

互斥鎖提供了以排他方式防止數據結構被併發修改的方法 讀寫鎖容許多個線程同時讀共享數據,而對寫操做是互斥的 條件變量能夠以原子的方式阻塞進程,直到某個特定條件爲真爲止。對條件的測試是在互斥鎖的保護下進行的。條件變量始終與互斥鎖一塊兒使用。 信號量機制:包括無名線程信號量和命名線程信號量

信號機制:相似進程間的信號處理 線程間的通訊目的只要是用於新城同步,因此線程沒有像進程通訊中的用於數據交換的通訊機制。

  1. 什麼是多線程環境下的僞共存(false sharing)

緩存系統中是以緩存行爲單位存儲的。緩存行是2的整數冪個連續字節,通常爲32-256個字節。最多見的緩存行大小是64個字節。當多線程修改互相獨立的變量時,若是這些變量共享同一個緩存航,就會無心中影響彼此的性能,這就是僞共存

  1. 同步和異步有何不一樣,在什麼狀況下分別使用它們?舉例說明

若是數據將在線程間共享。例如:正在寫的數據之後可能會被另外一個線程讀到,或者正在讀的數據可能已經被另外一個線程寫過了,那麼這些數據就是共享數據,必須進行同步存取 當應用程序在對象上調用了一個須要花費很長時間來執行的方法,而且不但願讓程序等待方法的返回時,就應該使用異步編程,在不少狀況下采用異步途徑每每更有效。 同步交互:指發送一個請求,須要等待返回,而後才能發送下一個請求,有個等待的過程 異步交互:指發送一個請求,不須要等待返回,隨時能夠再發送下一個請求,即不須要等待。 區別:一個須要等待,一個不須要等待

  1. ConcurrentHashMap 和 Hashtable的區別

它們均可以用於多線程的環境,但當Hashtable的大小增長到必定的時候,性能會急劇降低,由於迭代時須要被鎖定很長的時間。

HashTable的任何操做都會把整個表鎖住,是阻塞的。好處是:總能獲取最實時的更新,好比說線程A調用putAll()寫入大量數據,期間線程B調用get(),線程B就會被阻塞,直到線程A完成putAll(),所以線程B確定能獲取到線程A寫入的完整數據。壞處是全部調用都須要排隊,效率較低。

ConcurrentHashMap是設計爲非阻塞的。在更新時會局部鎖住某部分數據,但不會把整個表都鎖住。同步讀取操做則是徹底非阻塞的。好處是在保證合理的同步前提下,效率很高。壞處是:嚴格來講,讀取操做不能保證反映最近的更新。例如線程A調用putAll()寫入大量數據,期間線程B調用get(),則只能get()到目前爲止已經順利插入的部分數據。

JDK8的版本,與JDK6的版本有很大差別。實現線程安全的思想也已經徹底變了,它摒棄了Segment(分段鎖)的概念,而是啓用了一種全新的方式實現,利用CAS算法。它沿用了與它同時期的HashMap版本的思想,底層依然由數組+鏈表+紅黑樹的方式思想,可是爲了作到併發,又增長了不少複製類,例如TreeBin、Traverser等對象內部類。CAS算法實現無鎖化的修改至操做,他能夠大大下降鎖代理的性能消耗。這個算法的基本思想就是不斷地去比較當前內存中的變量值與你指定的一個變量值是否相等,若是相等,則接受你指定的修改的值,不然拒絕你的操做。由於當前線程中的值已經不是最新的值,你的修改極可能會覆蓋掉其餘線程修改的結果。

  1. Hashtable與Hashmap的區別 HashTable與Hashmap都實現了Map接口,可是Hashtable的實現是基於Dictionary抽象類。 在HashMap中,null能夠做爲鍵,這樣的鍵只能有一個;能夠有一個或者多個鍵所對應的值爲null;當get()方法返回null時,既能夠表示Hashmap中沒有該鍵,也能夠表示該鍵鎖對應的值爲null。所以,在Hashmap中不能由get()方法來判斷HashMap中是否存在某個鍵,而應該使用containsKey()方法來判斷。 在HashTable中,不管鍵key仍是值value都不能爲null

這兩個 類最大的不一樣之處在於:

HashTable是線程安全的,它的方法是同步的,能夠直接用於多線程環境中 HashMap是線程不安全的,在多線程環境中,須要手動實現同步機制

  1. ArrayBlockingQueue的用法

一個線程向一個固定大小的隊列裏面不停地存放數據,另外一個線程不停地向這個隊列裏面取數據,當隊列滿了,還繼續存放數據,此時出現阻塞,直到隊列有空閒的位置;反之,當隊列爲空,還繼續取數據,則也出現阻塞,直到隊列中有數據爲止

  1. CountDownLatch的用法

CountDownLatch能夠控制線程的執行,它可讓全部持有它的多個線程同時執行,也能夠控制單個線程執行。 它在初始化的時候會傳入一個int類型的參數i,調用一次countDown方法後i的值回減1。 在一個線程中若是調用了await()方法,這個線程就會進入等待的狀態,當參數i爲爲0的時候這個線程才繼續執行 例子: 好比一個跑步比賽,有5個選手參加,有兩點須要注意,第一咱們必須確保這5個選手都準備就緒了,才能宣佈比賽開始,第二隻有當5個選手都完成比賽了才能宣佈比賽結束。

因此假設這5個選手都有一個獨立的線程進行跑步,那麼每一個線程都必須持有一個相同的CountDownLatch,而且調用await()進入等待狀態,而後才能確保他們同時開始比賽。

同時能夠主線程中也要持有一個CountDownLatch,當選手開始比賽後要進入等待狀態,等待全部的選手都完成比賽才能宣佈比賽結束。

  1. CountDownLatch與CyclicBarrier有什麼不一樣?各自內部原理和用法是什麼

CountDownLatch能夠理解爲倒計時鎖,這個類可以使一個線程等待其餘縣城完成各自的工做後再執行,應用程序的主線程但願在負責啓動框架服務的線程已經啓動全部框架服務後再執行。CountDownLatch不能夠從新使用

CyclicBarrier能夠當作是障礙,全部線程必須到齊後才能一塊兒經過這個障礙。場景:公司組織戶外拓展活動,幫助團建,其中最重要的一個項目就是全體員工在完成其餘項目時,到達一個高達4米的高牆,沒有任何抓點,要求全部人,一個不能少的越太高牆,才能繼續進行其餘項目。CyclicBarrier能夠從新使用

  1. 線程和進程有什麼區別

線程是進程的子集,一個進程能夠有不少線程,每條線程並行執行不一樣的任務。不一樣的進程使用不一樣的內存空間,而全部的線程共享一片相同的內存空間。

  1. 用Runnable仍是用Thread

你們知道咱們能夠經過繼承Thread類或者調用Runnable接口來實現線程,問題是,哪一個方法更好呢?什麼狀況下使用哪一種呢?若是你要繼承其餘的類,就實現Runnable接口

  1. Thread類中的strat()和run()方法有什麼區別?

start()方法被用來啓動新建立的線程,並且start()內部調用了run()方法,這和直接調用run()方法的效果不同。當你調用run()方法的時候,只會在原來的線程中調用,沒有新的線程啓動,而調用start()方法會啓動一個新的線程。

  1. java中Runnable和Callable的區別

Runnable和Callable都表明那些要在不一樣的線程中執行的任務。Runnable從JDK1.0開始就有了,Callable是在JDK1.5增長的。 他們的主要區別是Callable的call()方法能夠返回值和拋出異常,而Runnable的run()方法沒有這些功能。Callable能夠返回裝載有計算結果的Future對象。

  1. 什麼是java內存模型

java內存模型定義了java虛擬機在計算機內存中的工做方式。JMM決定了一個線程對共享變量的寫入什麼時候對另外一個線程可見。從抽象的角度來看,JMM定義了線程和主內存之間的抽象關係:線程之間的共享變量存儲在主內存中,每個線程都有一個私有的本地內存,本地內存中存儲了該線程以讀/寫共享變量的副本。

  1. 什麼是線程安全?

若是你的代碼所在的進程中有多個線程在同時運行,而這些線程可能會同時運行這段代碼。若是每次運行結果和單線程運行的結果都是同樣的,並且其餘變量的值也和預期的是同樣的,就是線程安全的。一個線程安全的計數器類的同一個實例對象在被多個線程使用的狀況下也不會出現計算失誤。

  1. java中什麼是競態條件

當某個計算的正確性取決於多個線程的交替執行時序時,那麼就會發生競態條件。換句話說,就是正確的結果要取決於運氣。最多見的競態條件類型就是「先檢查後執行」操做,即經過一個可能失敗的觀測結果來決定下一步的動做。

  1. java中如何中止一個線程

java提供了很豐富的API但沒有爲中止線程提供API。JDK1.0原本有一些像stop()、suspend()和resume()的控制方法可是因爲潛在的死鎖威脅,所以在後續的JDK版本中他們被摒棄了,以後Java

API的設計者就沒有提供一個兼容且線程安全的方法來中止一個線程。當run()或者call()方法執行完的時候線程會自動結束,若是要手動結束一個線程,你可使用volatile布爾變量來推出run()方法的循環或者是取消任務來中斷線程

  1. 一個線程運行時發生異常會怎樣?

若是異常沒有被捕獲該線程將會中止執行。 Thread.UncaughtExceptionHandler是用於處理未捕獲異常形成線程忽然中斷狀況的一個內嵌藉口。當一個未捕獲異常將形成線程中斷的時候JVM會使用Thread.getUncaughtExceptionHandler來查詢線程的UncaughtExceptionHandler並將線程和異常做爲參數傳遞給handler的uncaughtException()方法進行處理

  1. 如何在兩個線程間共享數據?

能夠經過共享對象來實現這個目的,或者是使用阻塞隊列,或者使用wait()和notify()方法

  1. 鎖池和等待池

鎖池:假設線程A已經擁有了某個對象的鎖,而其它的線程想要調用這個對象的某個Synchronized方法(或者Synchronized代碼塊),因爲這些線程在進入對象的synchronized方法以前必須先得到該對象的鎖的擁有權,可是該對象的鎖目前正被線程A擁有,因此這個線程就進入了該對象的鎖池中

等待池:假設一個線程A調用了某個對象的wait()方法,線程A就會釋放該對象的鎖後,進入到該對象的等待池中。

  1. java中的notify和notifyAll有什麼區別?

若是線程調用了對象的wait()方法,那麼線程便會處於該對象的等待池中,等待池中的線程不會去競爭該對象的鎖 當有線程調用了對象的notifyAll()方法(喚醒全部wait線程)或者notify()方法(只隨機喚醒一個wait線程),被喚醒的線程便會進入該對象的鎖池中,鎖池中的線程會去競爭該對象鎖。也就是說,調用了notify方法後只要一個線程會由等待池進入鎖池,而notifyAll方法會將該對象等待池內的全部線程移動到鎖池中,等待鎖競爭

優先級高的線程競爭到對象鎖的機率大,倘若某線程沒有競爭到該對象鎖,它還會留在鎖池中,惟有線程再次調用wait()方法,它纔會從新回到等待池中。而競爭到對象鎖的線程則繼續往下執行,直到執行完了synchronized代碼塊,它會釋放掉該對象鎖,這時鎖池中的線程會繼續競爭該對象鎖。 notify可能會產生死鎖

  1. 爲何wait、notify和notifyAll這些方法再也不thread類裏面

這是個設計相關的問題,它考察的是面試者對現有系統和一些廣泛存在但看起來不合理的事務的見解。回答這類問題的時候,你要說明爲何把這些方法放在Object類裏是有意義的,還有不把它放在Thread類裏的緣由。一個很明顯的緣由是java提供的鎖時對象級的而不是線程級的,每一個對象都有所,經過線程得到。若是線程須要等待某些鎖那麼調用對象中的wait()方法就有意義了。若是wait()方法定義在thread類中,線程正在等待的是哪一個鎖就不明顯了。

  1. 什麼是FutureTask?

在java併發程序中FutureTask表示一個能夠取消的異步運算。它有啓動和取消運算、查詢運算是否完成和取回運算結果等方法。只有當運算完成的時候結果才能返回,若是運算還沒有完成,get()方法將會阻塞。一個FutureTask對象能夠對調用了Callable和Runnable的對象進行包裝,因爲FutureTask也是調用了Runnbale接口因此它能夠提交給Executor來執行

  1. java中interrupted和isInterrupted方法的區別

interrupted()和isInterrupted()的主要區別是前者會將當前線程的中斷狀態清除然後者不會。 java多線程的中斷機制是用內部標誌來實現的,調用Thread.interrupt()來中斷一個線程就會設置中斷標誌爲true。當中斷線程調用靜態方法Thread.interrupt()來檢查中斷中斷時,中斷狀態會被清零。而非靜態方法isInterrupted()用來查詢其餘線程的中斷狀態且不會改變中斷狀態標識。

  1. 爲何wait和notify方法要在同步快中調用?

主要是由於java API強制要求這樣作,若是你不這樣作,你的代碼會拋出IllegalMonitorStateException異常。 爲了不wait和notify之間產生競態條件

  1. 爲何你應該在循環中檢查等待條件

處於等待狀態的線程可能會受到錯誤警報和僞喚醒,若是不在循環中檢查等待條件,程序就會在沒有知足結束條件的狀況下推出。所以,當一個等待線程醒來時,不能認爲它原來的等待狀態仍然是有效的,在notify()方法調用以後和等待線程醒來以前這段時間它可能會改變。這就是在循環中使用wait()方法效果更好的緣由。

  1. java中堆和棧有什麼不一樣?

爲何把這個問題歸類在多線程和併發面試題裏?由於棧是一塊和線程緊密相關的內存區域。每一個線程都有本身的棧內存,用於存儲本地變量、方法參數和棧調用,一個線程中存儲的變量對其餘線程是不可見的。而堆是全部線程共享的一片公共內存區域。對象都在堆裏建立,爲了提高效率,線程會從堆中弄一個緩存到本身的棧,若是多個線程使用該變量就可能引起問題,這時volatile變量就能夠發揮做用了,它要求線程從主存中讀取變量的值

  1. 什麼是線程池?爲何要使用它?

建立線程須要花費昂貴的資源和時間,若是任務來了才建立線程那麼響應時間會變成,並且一個進程能建立的線程數有限。爲了不這些問題,在程序啓動的時候就建立若干線程來響應處理,他們被稱爲線程池,裏面的線程叫工做線程。從JDK1.5開始,java API提供了Executor框架讓你能夠建立不一樣的線程池。好比單線程吃,數目固定的線程池等

  1. 如何避免死鎖?

java多線程中的死鎖:是指兩個或者兩個以上的進程在執行過程當中,因爭奪資源而形成的一種互相等待的現象,若無外力做用,它們都將沒法推動下去。這是一個嚴重的問題,所以死鎖會讓你的程序掛起沒法完成任務,死鎖的發生必須知足一下四個條件

互斥條件:一個資源每次只能被一個進程使用

請求與保持條件:一個進程因請求資源而阻塞時,對已得到的資源保持不放

不剝奪條件:進程已得到的資源,在未使用完以前,不能強行剝奪

循環等待條件:若干進程之間造成一種頭尾相接的循環等待資源關係

避免死鎖最簡單的方法就是阻塞循環等待條件,將系統中全部資源設置標誌位、排序,規定全部的進程申請資源必須以必定的順序(升序或者降序)作操做來避免死鎖

  1. java中活鎖和死鎖有什麼區別?

活鎖和死鎖相似,不一樣之處在於活鎖的線程或進程的狀態是不斷改變的,活鎖能夠認爲是一種特殊的飢餓。一個現實的活鎖例子就是:兩我的在狹小的走廊碰到,兩我的都試着避讓對方好讓彼此經過,可是由於避讓的方向都一直致使最後誰都不能經過走廊。簡單的說就是,活鎖和死鎖的主要區別是前者進程的狀態能夠改變可是卻不能繼續執行。

  1. 怎麼檢測一個線程是否擁有鎖?

在java.lang.Thread中有一個方法叫holdsLock()方法,當且晉檔當前線程擁有某個具體對象的鎖時它返回true。

  1. 若是在java中獲取線程堆棧?

對於不一樣的操做系統,有不少方法來得到java進程的線程堆棧。當你獲取線程堆棧時,JVM會把全部線程的狀態存到日誌文件或者輸出到控制檯。在Windows下可使用Ctrl + Break組合鍵來獲取線程堆棧,Linux下用kill -3命令

也可使用jstack這個工具來獲取,它對線程id進行操做,能夠用jps工具找到id

  1. java中synchronized和ReentrantLock有什麼不一樣?

java在過去很長一段時間只能經過synchronized關鍵字來實現互斥,它有一些缺點。好比你不能擴展鎖之外的方法或者塊邊界,嘗試獲取鎖時不能中途取消等。java5 經過Lock接口提供了更復雜的控制來解決這些問題。ReentrantLock類實現了Lock,它擁有與synchronized相同的併發性和內存語義且它還具備可擴展性。

  1. 有三個線程T一、T2和T3,怎麼確保它們按照順序執行?

在多線程中有多重方法讓線程按特定的順序執行,你能夠用線程類的join()方法在一個線程中啓動另外一個線程,另一個線程完成該線程繼續執行。爲了確保三個線程的順序你應該先啓動最後一個(T3調用T2,T2調用T1),這樣T1就會先完成而T3最後完成

  1. Thread類中的yield方法有什麼做用?

yield方法能夠暫停當前正在執行的線程對象,讓其餘有相同優先級的線程執行。它是一個靜態方法並且只保證當前線程放棄CPU佔用而不能保證使其餘線程必定能佔用CPU,執行yield的線程有可能在進入到暫停狀態後立刻又被執行

  1. java中ConcurrentHashMap的併發度是什麼?

ConcurrentHashMap把實際map劃分紅若干部分來實現它的可擴展性和線程安全。這種劃分是使用併發度得到的,它是ConcurrentHashMap類構造函數的一個可選參數,默認值爲16,這樣在多線程狀況下就能避免爭用。

  1. java中的Semaphore是什麼?

java中的Semaphore是一種新的同步類,它是一個記數信號。從概念上將,信號量維護了一個許可集合。若是必要,在許可可用前會阻塞每個acquire(),而後再獲取該許可。每一個release()添加一個許可,從而可能釋放一個正在阻塞的得到者。可是,不使用實際的許可對象,Semaphore只對可用許可的號碼進行技術,並採起相應的行動。信號量經常用於多線程的代碼中,好比數據庫鏈接池。

  1. 若是你提交任務時,線程池隊列已滿時會發生什麼?

若是一個任務不能被調度執行那麼ThreadPoolExecutor的submit()方法將會拋出一個RejectedExecutionException異常

  1. java線程池中submit()和execute()方法有什麼區別?

兩個方法均可以向線程池提交任務,execute()方法的返回類型時void,它定義在Executor接口中,而submit()方法能夠返回持有計算結果的Future對象,它定義在ExecutorService接口中,它擴展了Executor接口。

  1. 什麼是阻塞式方式?

阻塞式方式是指程序會一直等待該方法完成期間不作其餘事情,ServiceSocket的accept()方法就是一直等待客戶端鏈接。這裏的阻塞是指調用結果返回以前,當前線程會被掛起,直到等到結果以後纔會返回。此外,還有異步和非阻塞式方法在任務完成前就返回。

  1. java中的ReadWriteLock是什麼?

通常而言,讀寫鎖是用來提高併發程序性能的鎖分離技術的成果。java中的ReadWriteLock是java5中新增的一個接口,一個ReadWriteLock維護一對關聯的鎖,一個用於只讀操做一個用於寫。在沒有寫線程的狀況下一個讀鎖可能會同時被多個讀線程持有。寫鎖是獨佔的,你可使用JDK中的ReentrantReadWriteLock來實現這個規則

  1. volatile變量和atomic變量由什麼不一樣?

首先volatile變量和atomic變量看起來很像,可是功能卻不同。

volatile變量能夠確保線性關係,即寫操做會發生在後續的讀操做以前,但它不能保證原子性。例如用volatile修飾count變量,那麼count++操做就不是原子性的。

AtomicInteger類提供的atomic方法可讓這種操做具備原子性,如:getAndIncrement()方法會原子性的進行增量操做把當前值加1.,其餘數據類型和引用變量也能夠進行類似操做。

  1. 若是同步塊內的線程拋出異常會發生什麼?

不管同步塊是正常是還異常退出,裏面的線程都會釋放鎖。

  1. 單例模式的雙檢鎖是什麼?

  2. 寫出3條你遵循的多線程最佳實踐

給你的線程起個有意義的名字

這樣能夠方便找bug或者追蹤。給線程起一個和它要完成的任務相關的名字,全部的主要框架甚至JDK都遵循這個最佳實踐 避免鎖定和縮小同步的範圍

鎖花費的代價高昂且上下文切換更耗費實踐空間,試試最低限度的使用同步和鎖,縮小臨界區。 多用同步類少用wait和notify

首先,CountDownLatch、Semaphore、CyclicBarrier和Exchanger這些同步類簡化了編碼操做,而用wait()和notify()很難實現對複雜控制流的控制。其次,這些類是由最好的企業編寫和維護在後續的JDK中它們還會不斷優化和完善,使用這些更高等級的同步工具你的程序能夠不費吹灰之力得到優化。 多用併發集合少用同步集合

併發集合比同步集合的可擴展性更好,因此在併發編程時使用併發集合效果更好。若是下次你須要用map,你應該首先想到用ConcurrentHashMap

  1. 如何強制啓動一個線程?

這個問題就像是如何強制進行Java垃圾回事,目前尚未方法,雖然你可使用System.gc()來進行垃圾回收,可是不保證能成功。在java裏面沒有辦法強制啓動一個線程,它是被線程調度器控制着且java沒有公佈相關的API

  1. java中fork join框架是什麼?

fork join框架是JDK 7 中出現的一款高效的工具,java開發人員能夠經過它充分利用現代服務器上的多處理器。它是專門爲了那些能夠地櫃劃分紅許多子模塊設計的,目的是將全部可用的處理能力用來提高程序的心梗。fork join框架一個巨大的優點是它使用了工做竊取算法,能夠完成更多任務的工做線程能夠從其餘線程中竊取任務來執行

  1. java多線程中調用wait()和sleep方法有什麼不一樣?

java程序中wait和sleep都會形成某種形式的暫停,它們能夠知足不一樣的須要。wait()方法用於線程間通訊,若是等待條件爲真切其餘線程被喚醒時它會釋放鎖,而sleep()方法僅僅釋放CPU資源或者讓當前線程中止執行一段時間,但不會釋放鎖。

  1. 如何強制啓動一個線程?

在線程操做中,可使用join()方法讓一個線程強制運行,線程強制運行期間,只有該線程擁有CPU的執行權,其餘線程沒法運行,必須等待此線程完成以後才能夠繼續執行。

  1. 什麼是線程組,爲何在Java中不推薦使用

雖然縣城組看上去頗有用處,實際上如今的程序開發中已經不推薦使用它了,主要有兩個緣由:

線程組TheadGroup對象中比較有用的方法是stop()、resume()和suspend()等方法,因爲這幾個方法會致使線程的安全問題(主要是死鎖的問題),已經被官方廢棄了,因此線程組自己的應用價值就大打折扣 線程組ThreadGroup不是線程安全的,這在使用過程當中獲取的信息並不全是及時有效的,這就下降了它的統計使用價值 雖然線程組如今已經不被推薦使用了,可是它在線程的異常處理方面仍是作出了必定的貢獻。當線程運行過程當中出現異常狀況時,在某些狀況下JVM會把線程的控制權交到線程關聯的線程組對象上來進行處理。

  1. 有哪些不一樣的線程生命週期

當線程被建立並啓動之後,它既不是一啓動就進入了執行狀態,也不是一直處於執行狀態。在線程的生命週期中,它要通過新建、就緒、運行、阻塞和死亡5種狀態。尤爲是當線程啓動之後,它不可能一直「霸佔」着CPU肚子運行,因此CPU須要在多調線程之間切換,因而線程狀態也會屢次在運行和阻塞之間切換。

相關文章
相關標籤/搜索