1. 程式人生 > >java面試寶典第三彈

java面試寶典第三彈

返回 管理 過程 網絡 臨界資源 hashtable 私有化 針對 刪除

Http和Https的區別

超文本傳輸協議HTTP協議被用於在Web瀏覽器和網站服務器之間傳遞信息,HTTP協議以明文方式發送內容,不提供任何方式的數據加密,如果攻擊者截取了Web瀏覽器和網站服務器之間的傳輸報文,就可以直接讀懂其中的信息,因此,HTTP協議不適合傳輸一些敏感信息,比如:信用卡號、密碼等支付信息。

  為了解決HTTP協議的這一缺陷,需要使用另一種協議:安全套接字層超文本傳輸協議HTTPS,為了數據傳輸的安全,HTTPS在HTTP的基礎上加入了SSL協議,SSL依靠證書來驗證服務器的身份,並為瀏覽器和服務器之間的通信加密。

一、HTTP和HTTPS的基本概念

  HTTP:是互聯網上應用最為廣泛的一種網絡協議,是一個客戶端和服務器端請求和應答的標準(TCP),用於從WWW服務器傳輸超文本到本地瀏覽器的傳輸協議,它可以使瀏覽器更加高效,使網絡傳輸減少。

  HTTPS:是以安全為目標的HTTP通道,簡單講是HTTP的安全版,即HTTP下加入SSL層,HTTPS的安全基礎是SSL,因此加密的詳細內容就需要SSL。

  HTTPS協議的主要作用可以分為兩種:一種是建立一個信息安全通道,來保證數據傳輸的安全;另一種就是確認網站的真實性。

二、HTTP與HTTPS有什麽區別?

  HTTP協議傳輸的數據都是未加密的,也就是明文的,因此使用HTTP協議傳輸隱私信息非常不安全,為了保證這些隱私數據能加密傳輸,於是網景公司設計了SSL(Secure Sockets Layer)協議用於對HTTP協議傳輸的數據進行加密,從而就誕生了HTTPS。簡單來說,HTTPS協議是由SSL+HTTP協議構建的可進行加密傳輸、身份認證的網絡協議,要比http協議安全。

  HTTPS和HTTP的區別主要如下:

  1、https協議需要到ca申請證書,一般免費證書較少,因而需要一定費用。

  2、http是超文本傳輸協議,信息是明文傳輸,https則是具有安全性的ssl加密傳輸協議。

  3、http和https使用的是完全不同的連接方式,用的端口也不一樣,前者是80,後者是443。

  4、http的連接很簡單,是無狀態的;HTTPS協議是由SSL+HTTP協議構建的可進行加密傳輸、身份認證的網絡協議,比http協議安全。

三、HTTPS的工作原理

  我們都知道HTTPS能夠加密信息,以免敏感信息被第三方獲取,所以很多銀行網站或電子郵箱等等安全級別較高的服務都會采用HTTPS協議。

HTTPHTTPS的區別-馬海祥博客

 客戶端在使用HTTPS方式與Web服務器通信時有以下幾個步驟,如圖所示。

  (1)客戶使用https的URL訪問Web服務器,要求與Web服務器建立SSL連接。

  (2)Web服務器收到客戶端請求後,會將網站的證書信息(證書中包含公鑰)傳送一份給客戶端。

  (3)客戶端的瀏覽器與Web服務器開始協商SSL連接的安全等級,也就是信息加密的等級。

  (4)客戶端的瀏覽器根據雙方同意的安全等級,建立會話密鑰,然後利用網站的公鑰將會話密鑰加密,並傳送給網站。

  (5)Web服務器利用自己的私鑰解密出會話密鑰。

  (6)Web服務器利用會話密鑰加密與客戶端之間的通信。

四、HTTPS的優點

  盡管HTTPS並非絕對安全,掌握根證書的機構、掌握加密算法的組織同樣可以進行中間人形式的攻擊,但HTTPS仍是現行架構下最安全的解決方案,主要有以下幾個好處:

  (1)使用HTTPS協議可認證用戶和服務器,確保數據發送到正確的客戶機和服務器;

  (2)HTTPS協議是由SSL+HTTP協議構建的可進行加密傳輸、身份認證的網絡協議,要比http協議安全,可防止數據在傳輸過程中不被竊取、改變,確保數據的完整性。

  (3)HTTPS是現行架構下最安全的解決方案,雖然不是絕對安全,但它大幅增加了中間人攻擊的成本。

  (4)谷歌曾在2014年8月份調整搜索引擎算法,並稱“比起同等HTTP網站,采用HTTPS加密的網站在搜索結果中的排名將會更高”。

五、HTTPS的缺點

  雖然說HTTPS有很大的優勢,但其相對來說,還是存在不足之處的:

  (1)HTTPS協議握手階段比較費時,會使頁面的加載時間延長近50%,增加10%到20%的耗電;

  (2)HTTPS連接緩存不如HTTP高效,會增加數據開銷和功耗,甚至已有的安全措施也會因此而受到影響;

  (3)SSL證書需要錢,功能越強大的證書費用越高,個人網站、小網站沒有必要一般不會用。

  (4)SSL證書通常需要綁定IP,不能在同一IP上綁定多個域名,IPv4資源不可能支撐這個消耗。

  (5)HTTPS協議的加密範圍也比較有限,在黑客攻擊、拒絕服務攻擊、服務器劫持等方面幾乎起不到什麽作用。最關鍵的,SSL證書的信用鏈體系並不安全,特別是在某些國家可以控制CA根證書的情況下,中間人攻擊一樣可行。

六、http切換到HTTPS

  如果需要將網站從http切換到https到底該如何實現呢?

這裏需要將頁面中所有的鏈接,例如js,css,圖片等等鏈接都由http改為https。例如:http://www.baidu.com改為https://www.baidu.com

  BTW,這裏雖然將http切換為了https,還是建議保留http。所以我們在切換的時候可以做http和https的兼容,具體實現方式是,去掉頁面鏈接中的http頭部,這樣可以自動匹配http頭和https頭。例如:將http://www.baidu.com改為//www.baidu.com。然後當用戶從http的入口進入訪問頁面時,頁面就是http,如果用戶是從https的入口進入訪問頁面,頁面即使https的。

JVM的原理及線上調優

1.創建JVM裝載環境和配置

2.裝載JVM.dll

3.初始化JVM.dll並掛界到JNIENV(JNI調用接口)實例

4.調用JNIEnv實例裝載並處理class類。

JVM的原理及線上調優

一、設計模式的分類

總體來說設計模式分為三大類:

創建型模式,共五種:工廠方法模式、抽象工廠模式、單例模式、建造者模式、原型模式。

結構型模式,共七種:適配器模式、裝飾器模式、代理模式、外觀模式、橋接模式、組合模式、享元模式。

行為型模式,共十一種:策略模式、模板方法模式、觀察者模式、叠代子模式、責任鏈模式、命令模式、備忘錄模式、狀態模式、訪問者模式、中介者模式、解釋器模式。

其實還有兩類:並發型模式和線程池模式。用一個圖片來整體描述一下:

二、設計模式的六大原則

1、開閉原則(Open Close Principle)

開閉原則就是說對擴展開放,對修改關閉。在程序需要進行拓展的時候,不能去修改原有的代碼,實現一個熱插拔的效果。所以一句話概括就是:為了使程序的擴展性好,易於維護和升級。想要達到這樣的效果,我們需要使用接口和抽象類,後面的具體設計中我們會提到這點。

2、裏氏代換原則(Liskov Substitution Principle)

裏氏代換原則(Liskov Substitution Principle LSP)面向對象設計的基本原則之一。 裏氏代換原則中說,任何基類可以出現的地方,子類一定可以出現。 LSP是繼承復用的基石,只有當衍生類可以替換掉基類,軟件單位的功能不受到影響時,基類才能真正被復用,而衍生類也能夠在基類的基礎上增加新的行為。裏氏代換原則是對“開-閉”原則的補充。實現“開-閉”原則的關鍵步驟就是抽象化。而基類與子類的繼承關系就是抽象化的具體實現,所以裏氏代換原則是對實現抽象化的具體步驟的規範。—— From Baidu 百科

3、依賴倒轉原則(Dependence Inversion Principle)

這個是開閉原則的基礎,具體內容:真對接口編程,依賴於抽象而不依賴於具體。

4、接口隔離原則(Interface Segregation Principle)

這個原則的意思是:使用多個隔離的接口,比使用單個接口要好。還是一個降低類之間的耦合度的意思,從這兒我們看出,其實設計模式就是一個軟件的設計思想,從大型軟件架構出發,為了升級和維護方便。所以上文中多次出現:降低依賴,降低耦合。

5、迪米特法則(最少知道原則)(Demeter Principle)

為什麽叫最少知道原則,就是說:一個實體應當盡量少的與其他實體之間發生相互作用,使得系統功能模塊相對獨立。

6、合成復用原則(Composite Reuse Principle)

原則是盡量使用合成/聚合的方式,而不是使用繼承。

單例對象(Singleton)是一種常用的設計模式。在Java應用中,單例對象能保證在一個JVM中,該對象只有一個實例存在。這樣的模式有幾個好處:

1、某些類創建比較頻繁,對於一些大型的對象,這是一筆很大的系統開銷。

2、省去了new操作符,降低了系統內存的使用頻率,減輕GC壓力。

3、有些類如交易所的核心交易引擎,控制著交易流程,如果該類可以創建多個的話,系統完全亂了。(比如一個軍隊出現了多個司令員同時指揮,肯定會亂成一團),所以只有使用單例模式,才能保證核心交易服務器獨立控制整個流程。

有哪些可以保持進程同步的方法進程同步的四種方法

1、臨界區(Critical Section:通過對多線程的串行化來訪問公共資源或一段代碼,速度快,適合控制數據訪問。

優點:保證在某一時刻只有一個線程能訪問數據的簡便辦法

缺點:雖然臨界區同步速度很快,但卻只能用來同步本進程內的線程,而不可用來同步多個進程中的線程。

2、互斥量(Mutex:為協調共同對一個共享資源的單獨訪問而設計的。

互斥量跟臨界區很相似,比臨界區復雜,互斥對象只有一個,只有擁有互斥對象的線程才具有訪問資源的權限。

優點:使用互斥不僅僅能夠在同一應用程序不同線程中實現資源的安全共享,而且可以在不同應用程序的線程之間實現對資源的安全共享。

缺點:互斥量是可以命名的,也就是說它可以跨越進程使用,所以創建互斥量需要的資源更多,所以如果只為了在進程內部是用的話使用臨界區會帶來速度上的優勢並能夠減少資源占用量。因為互斥量是跨進程的互斥量一旦被創建,就可以通過名字打開它。

通過互斥量可以指定資源被獨占的方式使用,但如果有下面一種情況通過互斥量就無法處理,比如現在一位用戶購買了一份三個並發訪問許可的數據庫系統,可以根據用戶購買的訪問許可數量來決定有多少個線程/進程能同時進行數據庫操作,這時候如果利用互斥量就沒有辦法完成這個要求,信號量對象可以說是一種資源計數器。

3、信號量(Semaphore:為控制一個具有有限數量用戶資源而設計。它允許多個線程在同一時刻訪問同一資源,但是需要限制在同一時刻訪問此資源的最大線程數目。互斥量是信號量的一種特殊情況,當信號量的最大資源數=1就是互斥量了。

優點:適用於對Socket(套接字)程序中線程的同步。(例如,網絡上的HTTP服務器要對同一時間內訪問同一頁面的用戶數加以限制,只有不大於設定的最大用戶數目的線程能夠進行訪問,而其他的訪問企圖則被掛起,只有在有用戶退出對此頁面的訪問後才有可能進入。)

缺點:信號量機制必須有公共內存,不能用於分布式操作系統,這是它最大的弱點;

信號量機制功能強大,但使用時對信號量的操作分散, 而且難以控制,讀寫和維護都很困難,加重了程序員的編碼負擔;

核心操作P-V分散在各用戶程序的代碼中,不易控制和管理,一旦錯誤,後果嚴重,且不易發現和糾正。

4、事件(Event: 用來通知線程有一些事件已發生,從而啟動後繼任務的開始。

優點:事件對象通過通知操作的方式來保持線程的同步,並且可以實現不同進程中的線程同步操作。

缺點:

總結:

臨界區不是內核對象,只能用於進程內部的線程同步,是用戶方式的同步。互斥、信號量是內核對象可以用於不同進程之間的線程同步(跨進程同步)。

互斥其實是信號量的一種特殊形式。互斥可以保證在某一時刻只有一個線程可以擁有臨界資源。信號量可以保證在某一時刻有指定數目的線程可以擁有臨界資源。

如何避免死鎖

避免死鎖的幾種方式:

設置加鎖順序

設置加鎖時限

死鎖檢測

設置加鎖順序(線程按照一定的順序加鎖):

死鎖發生在多個線程需要相同的鎖,但是獲得不同的順序。

假如一個線程需要鎖,那麽他必須按照一定得順序獲得鎖。

例如加鎖順序是A->B->C,現在想要線程C想要獲取鎖,那麽他必須等到線程A和線程B獲取鎖之後才能輪到他獲取。(排隊執行,獲取鎖)

缺點:

按照順序加鎖是一種有效的死鎖預防機制。但是,這種方式需要你事先知道所有可能會用到的鎖,並知道他們之間獲取鎖的順序是什麽樣的。

設置加鎖時限:(超時重試)

在獲取鎖的時候嘗試加一個獲取鎖的時限,超過時限不需要再獲取鎖,放棄操作(對鎖的請求。)。

若一個線程在一定的時間裏沒有成功的獲取到鎖,則會進行回退並釋放之前獲取到的鎖,然後等待一段時間後進行重試。在這段等待時間中其他線程有機會嘗試獲取相同的鎖,這樣就能保證在沒有獲取鎖的時候繼續執行比的事情。

缺點:

但是由於存在鎖的超時,通過設置時限並不能確定出現了死鎖,每種方法總是有缺陷的。有時為了執行某個任務。某個線程花了很長的時間去執行任務,如果在其他線程看來,可能這個時間已經超過了等待的時限,可能出現了死鎖。

在大量線程去操作相同的資源的時候,這個情況又是一個不可避免的事情,比如說,現在只有兩個線程,一個線程執行的時候,超過了等待的時間,下一個線程會嘗試獲取相同的鎖,避免出現死鎖。但是這時候不是兩個線程了,可能是幾百個線程同時去執行,大的基數讓事件出現的概率變大,假如線程還是等待那麽長時間,但是多個線程的等待時間就有可能重疊,因此又會出現競爭超時,由於他們的超時發生時間正好趕在了一起,而超時等待的時間又是一致的,那麽他們下一次又會競爭,等待,這就又出現了死鎖。

死鎖檢測:

當一個線程獲取鎖的時候,會在相應的數據結構中記錄下來,相同下,如果有線程請求鎖,也會在相應的結構中記錄下來。當一個線程請求失敗時,需要遍歷一下這個數據結構檢查是否有死鎖產生。

例如:線程A請求鎖住一個方法1,但是現在這個方法是線程B所有的,這時候線程A可以檢查一下線程B是否已經請求了線程A當前所持有的鎖,像是一個環,線程A擁有鎖1,請求鎖2,線程B擁有鎖2,請求鎖1

當遍歷這個存儲結構的時候,如果發現了死鎖,一個可行的辦法就是釋放所有的鎖,回退,並且等待一段時間後再次嘗試。

缺點:

這個這個方法和上面的超時重試的策略是一樣的。但是在大量線程的時候問題還是會出現和設置加鎖時限相同的問題。每次線程之間發生競爭。

還有一種解決方法是設置線程優先級,這樣其中幾個線程回退,其余的線程繼續保持著他們獲取的鎖,也可以嘗試隨機設置優先級,這樣保證線程的執行。

死鎖產生的原因

1) 系統資源的競爭

通常系統中擁有的不可剝奪資源,其數量不足以滿足多個進程運行的需要,使得進程在 運行過程中,會因爭奪資源而陷入僵局,如磁帶機、打印機等。只有對不可剝奪資源的競爭 才可能產生死鎖,對可剝奪資源的競爭是不會引起死鎖的。

2) 進程推進順序非法

進程在運行過程中,請求和釋放資源的順序不當,也同樣會導致死鎖。例如,並發進程 P1P2分別保持了資源R1R2,而進程P1申請資源R2,進程P2申請資源R1時,兩者都 會因為所需資源被占用而阻塞。

信號量使用不當也會造成死鎖。進程間彼此相互等待對方發來的消息,結果也會使得這 些進程間無法繼續向前推進。例如,進程A等待進程B發的消息,進程B又在等待進程A 發的消息,可以看出進程AB不是因為競爭同一資源,而是在等待對方的資源導致死鎖。

3) 死鎖產生的必要條件

產生死鎖必須同時滿足以下四個條件,只要其中任一條件不成立,死鎖就不會發生。

互斥條件:進程要求對所分配的資源(如打印機)進行排他性控制,即在一段時間內某 資源僅為一個進程所占有。此時若有其他進程請求該資源,則請求進程只能等待。

不剝奪條件:進程所獲得的資源在未使用完畢之前,不能被其他進程強行奪走,即只能 由獲得該資源的進程自己來釋放(只能是主動釋放)

請求和保持條件:進程已經保持了至少一個資源,但又提出了新的資源請求,而該資源 已被其他進程占有,此時請求進程被阻塞,但對自己已獲得的資源保持不放。

循環等待條件:存在一種進程資源的循環等待鏈,鏈中每一個進程已獲得的資源同時被 鏈中下一個進程所請求。即存在一個處於等待狀態的進程集合{Pl, P2, ..., pn},其中Pi等 待的資源被P(i+1)占有(i=0, 1, ..., n-1)Pn等待的資源被P0占有,如圖2-15所示。

常見的數據結構有哪些

1)線性數據結構:元素之間一般存在元素之間存在一對一關系,是最常用的一類數據結構,典型的有:數組、棧、隊列和線性表

2)樹形結構:結點間具有層次關系,每一層的一個結點能且只能和上一層的一個結點相關,但同時可以和下一層的多個結點相關,稱為一對多關系,常見類型有:樹、堆

3)圖形結構:在圖形結構中,允許多個結點之間相關,稱為多對多關系

1、線性數據結構:典型的有:數組、棧、隊列和線性表

1)數組和鏈表

a、數組:存放著一組相同類型的數據,需要預先指定數組的長度,有一維數組、二維數組、多維數組等

b、鏈表:鏈表是C語言中一種應用廣泛的結構,它采用動態分配內存的形式實現,用一組任意的存儲單元存放數據元素鏈表的,一般為每個元素增設指針域,用來指向後繼元素

c、數組和鏈表的區別:

從邏輯結構來看:數組必須事先定義固定的長度,不能適應數據動態地增減的情況;鏈表動態地進行存儲分配,可以適應數據動態地增減的情況,且可以方便地插入、刪除數據項(數組中插入、刪除數據項時,需要移動其它數據項)

從內存存儲來看:(靜態)數組從棧中分配空間(用NEW創建的在堆中), 對於程序員方便快速,但是自由度小;鏈表從堆中分配空間, 自由度大但是申請管理比較麻煩

從訪問方式來看:數組在內存中是連續存儲的,因此,可以利用下標索引進行隨機訪問;鏈表是鏈式存儲結構,在訪問元素的時候只能通過線性的方式由前到後順序訪問,所以訪問效率比數組要低

2)棧、隊列和線性表:可采用順序存儲和鏈式存儲的方法進行存儲

順序存儲:借助數據元素在存儲空間中的相對位置來表示元素之間的邏輯關系

鏈式存儲:借助表示數據元素存儲地址的指針表示元素之間的邏輯關系

查找單鏈表中倒數第K個節點的算法

查找單鏈表中倒數第K個節點的算法

平時怎麽拓展自己的專業知識水平

1、sleep()和wait()方法的區別

對於sleep()方法,我們首先要知道該方法是屬於Thread類中的。而wait()方法,則是屬於Object類中的。

sleep()方法導致了程序暫停執行指定的時間,讓出cpu該其他線程,但是他的監控狀態依然保持者,當指定的時間到了又會自動恢復運行狀態。

在調用sleep()方法的過程中,線程不會釋放對象鎖。

而當調用wait()方法的時候,線程會放棄對象鎖,進入等待此對象的等待鎖定池,只有針對此對象調用notify()方法後本線程才進入對象鎖定池準備

獲取對象鎖進入運行狀態。

2、類為什麽要有hashcode()方法,是不是主要在集合類中都要實現hashcode方法

 對於包含容器類型的程序設計語言來說,基本上都會涉及到hashCode。在Java中也一樣,hashCode方法的主要作用是為了配合基於散列的集合一起正常運行,這樣的散列集合包括HashSetHashMap以及HashTable

  為什麽這麽說呢?考慮一種情況,當向集合中插入對象時,如何判別在集合中是否已經存在該對象了?(註意:集合中不允許重復的元素存在)

  也許大多數人都會想到調用equals方法來逐個進行比較,這個方法確實可行。但是如果集合中已經存在一萬條數據或者更多的數據,如果采用

equals方法去逐一比較,效率必然是一個問題。此時hashCode方法的作用就體現出來了,當集合要添加新的對象時,先調用這個對象的

hashCode方法,得到對應的hashcode值,實際上在HashMap的具體實現中會用一個table保存已經存進去的對象的hashcode

值,如果table中沒有該hashcode值,它就可以直接存進去,不用再進行任何比較了;如果存在該hashcode值,

就調用它的equals方法與新元素進行比較,相同的話就不存了,不相同就散列其它的地址,所以這裏存在一個沖突解決的問題,這樣一來實際調用

equals方法的次數就大大降低了,說通俗一點:Java中的hashCode方法就是根據一定的規則將與對象相關的信息(比如對象的存儲地址,對象的

字段等)映射成一個數值,這個數值稱作為散列值。

hashCode方法的存在是為了減少equals方法的調用次數,從而提高程序效率

設計一個標準的實體類四大原則:

1、封裝:屬性私有化,提供get/set方法等;

2、提供無參構造;

3、重寫toString()、HashCode()、equals()這三個方法,(繼承自根Object,不必須都重寫按自己的需求定);

4、實現序列化接口(implements Serializable),這樣類的對象可以經過二進制數據流進行傳輸。

//3、equals()方法怎麽實現

4、兩個不同的對象可能有相同的hashcode值嗎

HashSetHashMap一直都是JDK中最常用的兩個類,HashSet要求不能存儲相同的對象,HashMap要求不能存儲相同的鍵。

那麽Java運行時環境是如何判斷HashSet中相同對象、HashMap中相同鍵的呢?當存儲了相同的東西之後Java運行時環境又將如何來維護呢?

在研究這個問題之前,首先說明一下JDKequals(Object obj)hashcode()這兩個方法的定義和規範:

Java中任何一個對象都具備equals(Object obj)hashcode()這兩個方法,因為他們是在Object類中定義的。

equals(Object obj)方法用來判斷兩個對象是否相同,如果相同則返回true,否則返回false

hashcode()方法返回一個int數,在Object類中的默認實現是將該對象的內部地址轉換成一個整數返回

接下來有兩個個關於這兩個方法的重要規範(我只是抽取了最重要的兩個,其實不止兩個)

規範1:若重寫equals(Object obj)方法,有必要重寫hashcode()方法,確保通過equals(Object obj)方法判斷結果為true的兩個對象具備相等的hashcode()返回值。說得簡單點就是:如果兩個對象相同,那麽他們的hashcode應該 相等。不過請註意:這個只是規範,如果你非要寫一個類讓equals(Object obj)返回truehashcode()返回兩個不相等的值,編譯和運行都是不會報錯的。不過這樣違反了Java規範,程序也就埋下了BUG

規範2:如果equals(Object obj)返回false,即兩個對象不相同,並不要求對這兩個對象調用hashcode()方法得到兩個不相同的數。說的簡單點就是:如果兩個對象不相同,他們的hashcode可能相同

根據這兩個規範,可以得到如下推論:

1、如果兩個對象equalsJava運行時環境會認為他們的hashcode一定相等。

2、如果兩個對象不equals,他們的hashcode有可能相等。

3、如果兩個對象hashcode相等,他們不一定equals

4、如果兩個對象hashcode不相等,他們一定不equals

這樣我們就可以推斷Java運行時環境是怎樣判斷HashSetHastMap中的兩個對象相同或不同了。我的推斷是:先判斷hashcode是否相等,再判斷是否equals

5、java countdounlatch的考察

CountDownLatch內部會維護一個初始值為線程數量的計數器,主線程執行await方法,如果計數器大於0,則阻塞等待。當一個線程完成任務後,計數器值減1。當計數器為0時,表示所有的線程已經完成任務,等待的主線程被喚醒繼續執行。

6、hashmap的實現原理,concurrentHashMap的實現原理,實現細節,怎麽實現同步的

首先,hashtable是同步的,也就是說,他是線程安全的,同時也意味著,單線程的時候,每次只能等一個線程處理完事情,釋放同步鎖,其他線程才可以處理。

所以速度也相應地變慢了。而hashmap是異步的。

其次,hashmap可以存儲null值的keyvaluehashtable不可以。

所以在單線程,不需要同步的時候,用hashmap

追求安全性,用hashtable

HashMap :先說HashMapHashMap線程不安全的,在並發環境下,可能會形成環狀鏈表(擴容時可能造成,具體原因自行百度google或查看源碼分析),導致get操作時,cpu空轉,所以,在並發環境中使用HashMap是非常危險的。

  HashTable HashTableHashMap的實現原理幾乎一樣,差別無非是1.HashTable不允許keyvaluenull2.HashTable是線程安全的。但是HashTable線程安全的策略實現代價卻太大了,簡單粗暴,get/put所有相關操作都是synchronized的,這相當於給整個哈希表加了一把大鎖,多線程訪問時候,只要有一個線程訪問或操作該對象,那其他線程只能阻塞,相當於將所有的操作串行化,在競爭激烈的並發場景中性能就會非常差。

 HashTable性能差主要是由於所有操作需要競爭同一把鎖,而如果容器中有多把鎖,每一把鎖鎖一段數據,這樣在多線程訪問時不同段的數據時,就不會存在鎖競爭了,這樣便可以有效地提高並發效率。這就是ConcurrentHashMap所采用的"分段鎖"思想。

Segment繼承了ReentrantLock,所以它就是一種可重入鎖(ReentrantLock)。在ConcurrentHashMap,一個Segment就是一個子哈希表,Segment裏維護了一個HashEntry數組,並發環境下,對於不同Segment的數據進行操作是不用考慮鎖競爭的。(就按默認的ConcurrentLeve16來講,理論上就允許16個線程並發執行,有木有很酷)

  所以,對於同一個Segment的操作才需考慮線程同步,不同的Segment則無需考慮。

Segment類似於HashMap,一個Segment維護著一個HashEntry數組

transient volatile HashEntry<K,V>[] table;

HashEntry是目前我們提到的最小的邏輯處理單元了。一個ConcurrentHashMap維護一個Segment數組,一個Segment維護一個HashEntry數組。

用分離鎖實現多個線程間的並發寫操作

HashEntery 對象的不變性來降低讀操作對加鎖的需求

Volatile 變量協調讀寫線程間的內存可見性

7、考察單例模式編寫,要線程安全且內存消耗小,劍指OFFER原題

單例模式是一種常見的設計模式;Java Singleton 模式就為我們提供了這樣實現的可能。使用Singleton的好處還在於可以節省內存,因為它限制了實例的個數,

有利於Java垃圾回收(garbage collection)。

單例模式也是一種比較常見的設計模式,它到底能帶給我們什麽好處呢?其實無非是三個方面的作用:

1、控制資源的使用,通過線程同步來控制資源的並發訪問;

2、控制實例產生的數量,達到節約資源的目的。

3、作為通信媒介使用,也就是數據共享,它可以在不建立直接關聯的條件下,讓多個不相關的兩個線程或者進程之間實現通信。

單例模式分三種:懶漢式單例、餓漢式單例、登記式單例三種。

單例模式有一下特點:

1、單例類只能有一個實例。

2、單例類必須自己創建自己的唯一實例。

3、單例類必須給所有其他對象提供這一實例。

java面試寶典第三彈