一.常用的設計模式有哪些
- 單例模式
- 裝飾模式:裝飾器模式(Decorator Pattern)允許向一個現有的對象添加新的功能,同時又不改變其結構。這種類型的設計模式屬於結構型模式,它是作爲現有的類的一個包裝。
- 工廠模式:定義一個創建對象的接口,讓其子類自己決定實例化哪一個工廠類,工廠模式使其創建過程延遲到子類進行。
- 代理模式:比如說:要訪問的對象在遠程的機器上。在面向對象系統中,有些對象由於某些原因(比如對象創建開銷很大,或者某些操作需要安全控制,或者需要進程外的訪問),直接訪問會給使用者或者系統結構帶來很多麻煩,我們可以在訪問此對象時加上一個對此對象的訪問層。
- 適配器模式:將一個類的接口轉換成客戶希望的另外一個接口。適配器模式使得原本由於接口不兼容而不能一起工作的那些類可以一起工作。
二、多線程
1.Thread和Runnable的區別?
1)可以避免由於Java的單繼承特性帶來的侷限。
2)實現資源共享。
2.多線程有哪些狀態?
創建、運行、阻塞、終止。
3)yield和join區別
yield方法暫停當前正在執行的線程對象。調用yield方法並不會讓線程進入阻塞狀態,而是讓線程重回就緒狀態,它只需要等待重新獲取CPU執行時間,這一點是和sleep方法不一樣的。【並不能保證一定會這樣,很少使用,一般調試和測試使用。】
join方法等待該線程終止。等待調用join方法的線程結束,再繼續執行。比如需要主線程等子線程運行結束。
4)wait和sleep區別
wait方法使當前線程進入阻塞狀態,如果指定時間,則在這個時間後自動喚醒,如果沒有指定時間,則要其他線程使用notify喚醒。和sleep區別爲wait方法會釋放鎖,sleep不同釋放同步方法的鎖。
3.線程池有哪幾種?
4.lock和synchronized區別?
當競爭資源非常激烈時(即有大量線程同時競爭),此時Lock的性能要遠遠優於synchronized
5.線程鎖有哪幾種?
ReentrantLock和ReentrantReadWriteLock
ReentrantReadWriteLock:對兩個線程如果同時讀,不需要鎖,會提高效率,寫讀和寫寫會加鎖。如果有一個線程已經佔用了讀鎖,則此時其他線程如果要申請寫鎖,則申請寫鎖的線程會一直等待釋放讀鎖。如果有一個線程已經佔用了寫鎖,則此時其他線程如果申請寫鎖或者讀鎖,則申請的線程會一直等待釋放寫鎖。
6.公平鎖和非公平鎖區別?
公平鎖即儘量以請求鎖的順序來獲取鎖。比如同是有多個線程在等待一個鎖,當這個鎖被釋放時,等待時間最久的線程(最先請求的線程)會獲得該所,這種就是公平鎖。
非公平鎖即無法保證鎖的獲取是按照請求鎖的順序進行的。這樣就可能導致某個或者一些線程永遠獲取不到鎖。
在Java中,synchronized就是非公平鎖,它無法保證等待的線程獲取鎖的順序。
而對於ReentrantLock和ReentrantReadWriteLock,它默認情況下是非公平鎖,但是可以設置爲公平鎖。
7.樂觀鎖和悲觀鎖區別?
悲觀鎖:總是假設最壞的情況,每次去拿數據的時候都認爲別人會修改,所以每次在拿數據的時候都會上鎖,這樣別人想拿這個數據就會阻塞直到它拿到鎖。傳統的關係型數據庫裏邊就用到了很多這種鎖機制,比如行鎖,表鎖等,讀鎖,寫鎖等,都是在做操作之前先上鎖。再比如Java裏面的同步原語synchronized關鍵字的實現也是悲觀鎖。
樂觀鎖:顧名思義,就是很樂觀,每次去拿數據的時候都認爲別人不會修改,所以不會上鎖,但是在更新的時候會判斷一下在此期間別人有沒有去更新這個數據,可以使用版本號等機制。樂觀鎖適用於多讀的應用類型,這樣可以提高吞吐量,像數據庫提供的類似於write_condition機制,其實都是提供的樂觀鎖。在Java中java.util.concurrent.atomic包下面的原子變量類就是使用了樂觀鎖的一種實現方式CAS實現的。
例如git提交代碼類似使用樂觀鎖,只有提交更新時纔會去檢測是否衝突,如果衝突返回給用戶去處理。