求职学习笔记|并发编程知识点常见问题总结(一)
1. 什么是阻塞隊列?阻塞隊列的實現原理是什么?
阻塞隊列(BlockingQueue)是一個支持兩個附加操作的隊列。
這兩個附加的操作是:在隊列為空時,獲取元素的線程會等待隊列變為非空。當隊列滿時,存儲元素的線程會等待隊列可用。
阻塞隊列常用于生產者和消費者的場景,生產者是往隊列里添加元素的線程,消費者是從隊列里拿元素的線程。阻塞隊列就是生產者存放元素的容器,而消費者也只從容器里拿元素。
2. 什么是 Callable 和 Future?
Callable接口類似于 Runnable,從名字就可以看出來了,但是Runnable不會返回結果,并且無法拋出返回結果的異常,而 Callable功能更強大一些,被線程執行后,可以返回值,這個返回值可以被Future拿到,也就是說,Future 可以拿到異步執行任務的返回值。可以認為是帶有回調的 Runnable。
Future接口表示異步任務,是還沒有完成的任務給出的未來結果。所以說 Callable 用于產生結果,Future 用于獲取結果。
3. 什么是 FutureTask?
在 Java 并發程序中FutureTask表示一個可以取消的異步運算。它有啟動和取消運算、查詢運算是否完成和取回運算結果等方法。只有當運算完成的時候結果才能取回,如果運算尚未完成 get方法將會阻塞。一個FutureTask對象可以對調用了 Callable 和 Runnable 的對象進行包裝,由于FutureTask也是調用了 Runnable接口所以它可以提交給 Executor 來執行。
4. notify ()和 notifyAll ()有什么區別?
當一個線程進入 wait 之后,就必須等其他線程notify/notifyall,使用 notifyall,可以喚醒所有處于 wait 狀態的線程,使其重新進入鎖的爭奪隊列中,而 notify只能喚醒一個。
如果沒把握,建議notifyAll,防止notify因為信號丟失而造成程序異常。
5. 什么是可重入鎖( ReentrantLock )?談談它的實現
線程可以重復進入任何一個它已經擁有的鎖所同步著的代碼塊,synchronized、ReentrantLock都是可重入的鎖。在實現上,就是線程每次獲取鎖時判定如果獲得鎖的線程是它自己時,簡單將計數器累積即可,每 釋放一次鎖,進行計數器累減,直到計算器歸零,表示線程已經徹底釋放鎖。
6. 樂觀鎖和悲觀鎖的理解及如何實現,有哪些實現方式?
悲觀鎖:總是假設最壞的情況,每次去拿數據的時候都認為別人會修改,所以每次在拿數據的時候都會上鎖,這樣別人想拿這個數據就會阻塞直到它拿到鎖。Java里面的同步原語synchronized關鍵字的實現是悲觀鎖。
樂觀鎖:顧名思義,就是很樂觀,每次去拿數據的時候都認為別人不會修改,所以不會上鎖,但是在更新的時候會判斷一下在此期間別人有沒有去更新這個數據,可以使用版本號等機制。在Java中原子變量類就是使用了樂觀鎖的一種實現方式 CAS 實現的。
樂觀鎖的實現方式:
使用版本標識來確定讀到的數據與提交時的數據是否一致。提交后修改版本標識,不一致時可以采取丟棄和再次嘗試的策略。
java 中的 Compare and Swap 即 CAS ,當多個線程嘗試使用 CAS 同時更新同一個變量時,只有其中一個線程能更新變量的值,而其它線程都失敗,失敗的線程并不會被掛起,而是被告知這次競爭中失敗,并可以再次嘗試。Java開發交流君樣:756584822
7. 什么是 CAS 操作,缺點是什么?
CAS 的基本思路就是,如果這個地址上的值和期望的值相等,則給其賦予新值,否則不做任何事兒,但是要返回原值是多少。每一個 CAS 操作過程都包含三個運算符:一個內存地址 V,一個期望的值 A 和一個新值 B,操作的時候如果這個地址上存放的值等于這個期望的值 A,則將地址上的值賦為新值 B,否則不做任何操作。
CAS 缺點
ABA 問題
比如說一個線程one從內存位置V中取出A,這時候另一個線程two也從內存中取出 A,并且two進行了一些操作變成了 B,然后 two又將V位置的數據變成A,這時候線程 one進行 CAS操作發現內存中仍然是 A然后one操作成功。盡管線程 one 的 CAS 操作成功,但可能存在潛藏的問題。從 Java1.5開始J DK 的 atomic包里提供了一個類 AtomicStampedReference 來解決 ABA 問題。
循環時間長開銷大:
對于資源競爭嚴重(線程沖突嚴重)的情況,CAS自旋的概率會比較大,從而浪費更多的 CPU 資源,效率低于 synchronized。
只能保證一個共享變量的原子操作:
當對一個共享變量執行操作時,我們可以使用循環 CAS 的方式來保證原子操作,但是對多個共享變量操作時,循環 CAS 就無法保證操作的原子性,這個時候就可以用鎖。
8. SynchronizedMap 和 ConcurrentHashMap 有什么區別?
1. Executor框架是一個根據一組執行策略調用,調度,執行和控制的異步任務的框架。每次執行任務創建線程 new
Thread()比較消耗性能,創建一個線程是比較耗時、耗資源的。
2. 調用 new
Thread()創建的線程缺乏管理,而且可以無限制的創建,線程之間的相互競爭會導致過多占用系統資源而導致系統癱瘓,還有線程之間的頻繁交替也會消耗很多系統資源。
接使用 new Thread()啟動的線程不利于擴展,比如定時執行、定期執行、定時定期執行、線程中斷等都不便實現。
9. 在 Java 中 wait 和 sleep 方法的不同?
最大的不同是在等待時 wait 會釋放鎖,而 sleep 一直持有鎖。Wait 通常被用于線程間交互,sleep 通常被用于暫停執行。
10. 一個線程運行時發生異常會怎樣?
如果異常沒有被捕獲該線程將會停止執行。Thread.UncaughtExceptionHandler是用于處理未捕獲異常造成線程突然中斷情況的一個內嵌接口。當一個未捕獲異常將造成線程中斷的時候 JVM 會使用 Thread.getUncaughtExceptionHandler ( ) 來查詢線程的UncaughtExceptionHandler并將線程和異常作為參數傳遞給handler的uncaughtException()方法進行處理。
最后,祝大家早日學有所成,拿到滿意offer
總結
以上是生活随笔為你收集整理的求职学习笔记|并发编程知识点常见问题总结(一)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 花呗延期后下个月可以最低还款吗?
- 下一篇: 股票分红钱打到哪里?