java容易掉发吗_容易被忽略的面试题—Java高并发
常見實現如CAS等。
部分樂觀鎖削弱了一致性,但中低并發程度下的效率大大提高。
并發編程
Java中如何創建一個線程?
從面相接口的角度上講,實際上只有一種方法實現Runable接口;但Thread類為線程操作提供了更多的支持,所以通常做法是實現Runable接口,實例化并傳入Thread類的構造函數。
繼承Thread,覆寫run方法
實現Runable接口,覆寫run方法
繼承Thread,覆寫run方法
實現Runable接口,覆寫run方法
Vector(HashTable)如何實現線程安全?
通過synchronized關鍵字修飾每個方法。
依據synchronized關鍵字引申出以下問題。
synchronized修飾方法和修飾代碼塊時有何不同?
持有鎖的對象不同:
修飾方法時:this引用的當前實例持有鎖
修飾代碼塊時:要指定一個對象,該對象持有鎖
修飾方法時:this引用的當前實例持有鎖
修飾代碼塊時:要指定一個對象,該對象持有鎖
從而導致二者的意義不同:
同步代碼塊在鎖定的范圍上可能比同步方法要小,一般來說鎖的范圍大小和性能是成反比的。
修飾代碼塊可以選擇對哪個對象加鎖,但是修飾方法只能給this對象加鎖。
同步代碼塊在鎖定的范圍上可能比同步方法要小,一般來說鎖的范圍大小和性能是成反比的。
修飾代碼塊可以選擇對哪個對象加鎖,但是修飾方法只能給this對象加鎖。
ConcurrentHashMap的如何實現線程安全?
ConcurrentHashMap的線程安全實現與HashTable不同:
可以將ConcurrentHashMap理解為,不直接持有一個HashMao,而是用多個Segment代替了一個HashMap。但實際實現的Map部分和HashMap的原理基本相同,對腳標取模來確定table[i]所屬段,從而對不同的段獲取不同的段鎖。
每個Segment持有一個鎖,通過分段加鎖的方式,既實現了線程安全,又兼顧了性能
可以將ConcurrentHashMap理解為,不直接持有一個HashMao,而是用多個Segment代替了一個HashMap。但實際實現的Map部分和HashMap的原理基本相同,對腳標取模來確定table[i]所屬段,從而對不同的段獲取不同的段鎖。
每個Segment持有一個鎖,通過分段加鎖的方式,既實現了線程安全,又兼顧了性能
實現并發線程的方法
要從最簡單的答起,業界最常用的是重點,有新意就放在最后。
1. synchronized關鍵字
2. 使用繼承自Object類的wait、notify、notifyAll方法
3. 使用線程安全的API和集合類:
使用Vector、HashTable等線程安全的集合類
使用Concurrent包中提供的ConcurrentHashMap、CopyOnWriteArrayList、ConcurrentLinkedQueue等弱一致性的集合類
在Collections類中有多個靜態方法,它們可以獲取通過同步方法封裝非同步集合而得到的集合,如List list = Collection.synchronizedList(new ArrayList())。
使用Vector、HashTable等線程安全的集合類
使用Concurrent包中提供的ConcurrentHashMap、CopyOnWriteArrayList、ConcurrentLinkedQueue等弱一致性的集合類
在Collections類中有多個靜態方法,它們可以獲取通過同步方法封裝非同步集合而得到的集合,如List list = Collection.synchronizedList(new ArrayList())。
4.使用原子變量、volatile變量等
5. 使用Concurrent包中提供的信號量Semaphore、閉鎖Latch、柵欄Barrier、交換器Exchanger、Callable&Future、阻塞隊列BlockingQueue等.
6. 手動使用Lock實現基于鎖的并發控制
7. 手動使用Condition或AQS實現基于條件隊列的并發控制
8. 使用CAS和SPIN等實現非阻塞的并發控制
使用不變類
9. 其他并發模型還沒有涉及
從而引申出如下問題:
ConcurrentHashMap的的實現原理
CopyOnWriteArrayList的復制操作發生在什么時機
synchronizedList&Vector的區別
ConcurrentHashMap的的實現原理
CopyOnWriteArrayList的復制操作發生在什么時機
synchronizedList&Vector的區別
synchronizedList的實現中,synchronized關鍵字修飾代碼塊;Vector的實現中修飾方法。
synchronizedList只封裝了add、get、remove等代碼塊,但Iterator卻不是同步的,進行遍歷時要手動進行同步處理;Vector中對Iterator也進行了加鎖。
synchronizedList能夠將所有List實現類封裝為同步集合,其內部持有的仍然是List的實現類(ArrayList/LinkedList),所以除同步外,幾乎只有該實現類和Vector的區別。synchronized修飾方法和修飾代碼塊時有何不同
synchronizedList的實現中,synchronized關鍵字修飾代碼塊;Vector的實現中修飾方法。
synchronizedList只封裝了add、get、remove等代碼塊,但Iterator卻不是同步的,進行遍歷時要手動進行同步處理;Vector中對Iterator也進行了加鎖。
synchronizedList能夠將所有List實現類封裝為同步集合,其內部持有的仍然是List的實現類(ArrayList/LinkedList),所以除同步外,幾乎只有該實現類和Vector的區別。synchronized修飾方法和修飾代碼塊時有何不同
信號量Semaphore、閉鎖Latch、柵欄Barrier、交換器
Exchanger、Callable&Future、阻塞隊列BlockingQueue的實現原理
ConcurrentLinkedQueue的插入算法
算法核心可概括為兩步:
先檢測是否是中間狀態(SPIN)
再嘗試CAS插入
先檢測是否是中間狀態(SPIN)
再嘗試CAS插入
在java中wait和sleep方法的不同?
最大的不同是在等待時wait會釋放鎖,而sleep一直持有鎖。Wait通常被用于線程間交互,sleep通常被用于暫停執行。
為什么wait, notify 和 notifyAll這些方法不在thread類里面?
主要原因是JAVA提供的鎖是對象級的而不是線程級的,每個對象都有鎖,通過線程獲得。由于wait,notify和notifyAll都是鎖級別的操作,所以把他們定義在Object類中因為鎖屬于對象。
為什么wait和notify方法要在同步塊中調用?
Java API強制要求這樣做,如果你不這么做,你的代碼會拋出IllegalMonitorStateException異常。還有一個原因是為了避免wait和notify之間產生競態條件。
為什么你應該在循環中檢查等待條件?
處于等待狀態的線程可能會收到錯誤警報和偽喚醒,如果不在循環中檢查等待條件,程序就會在沒有滿足結束條件的情況下退出。
Java線程池中submit() 和 execute()方法有什么區別?
兩個方法都可以向線程池提交任務,execute()方法的返回類型是void,它定義在Executor接口中, 而submit()方法可以返回持有計算結果的Future對象,它定義在ExecutorService接口中,它擴展了Executor接口,其它線程池類像ThreadPoolExecutor和ScheduledThreadPoolExecutor都有這些方法。
volatile 變量和 atomic 變量有什么不同?
Volatile變量可以確保先行關系,即寫操作會發生在后續的讀操作之前, 但它并不能保證原子性。例如用volatile修飾count變量那么 count++ 操作就不是原子性的。而AtomicInteger類提供的atomic方法可以讓這種操作具有原子性如getAndIncrement()方法會原子性的進行增量操作把當前值加一,其它數據類型和引用變量也可以進行相似操作。
為什么Thread類的sleep()和yield ()方法是靜態的?
Thread類的sleep()和yield()方法將在當前正在執行的線程上運行。所以在其他處于等待狀態的線程上調用這些方法是沒有意義的。這就是為什么這些方法是靜態的。它們可以在當前正在執行的線程中工作,并避免程序員錯誤的認為可以在其他非運行線程調用這些方法。
本文整理自 ImportNew
來源:猴子007
(完)
恭喜你今天又獲得了新知識
喜訊 :
總結
以上是生活随笔為你收集整理的java容易掉发吗_容易被忽略的面试题—Java高并发的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java 变参 使用数组调用_java中
- 下一篇: 将类似html数据打印机,机器人和3D打