Java常考面試題(四)

一杯涼茶發表於2016-11-14

      序言

        雙十一那天去我女朋友那了,11.11到11.13 漏了兩天的內容,今天中午剛回來的,趕緊補一下前兩天漏下的博文,我相信,堅持下來,會有成長的,等到出去實習那一天,肯定會很有幫助,會感謝現在自己的努力。

        對了,因為常常會被別人影響到自己,看到別人努力,自己玩了兩天就感覺心裡好慌啊,每到這個時候,我就告訴自己:不與他人相比,但求超越自己, 希望有跟同樣情況的同學也能這樣來安撫自己那顆躁動的心,踏踏實實,按照自己的節奏走下去。

                                                                                    ---  WH

一、什麼是死鎖(deadlock)?

      自我解答:

            這個問題,依稀在講解資料庫時有學習過。不過忘記的差不多了,大概就是A有一把鎖,B也有一把鎖,現在A獲得了B這把鎖,此時,A失去CPU,B又獲得了A這吧鎖,此時就造成了死鎖,因為雙方都解不開了。

      參考答案:

            兩個執行緒或兩個以上執行緒都在等待對方執行完畢才能繼續往下執行的時候就發生了死鎖。結果就是這些執行緒都陷入了無限的等待中。

 

      自我評價:

            順便把其他情況也複習一下,感覺這個需要理解,自己對這個概念也有點模糊不清。

            1、死鎖:A等待B、B等待A,造成死鎖,無限的等待中,

            2、死鎖的問題我就想到了複習一下資料庫的事務的特性和隔離級別吧

                什麼是事務?一組業務邏輯,注意,是一組。例如,A轉錢給B A就要有更新語句,B也要有更新語句,這兩個一起才是一個事務。

              事務的特性:ACID

                A:原子性,就是事務不可被劃分,是一個整體,要麼一起成功,要麼就一起失敗

                C:一致性:銀行轉賬,A轉走100塊給B,A減少100,那麼B就增加100

                I:隔離性:比較麻煩的點,多個事務對同一個內容的併發操作

                D:永續性:已經提交的事務,就已經儲存到資料庫中,不能再更改了。

              事務隔離性產生的問題

                1、髒讀:事務 讀取到了 另一個事務還未提交的資料。

                   例如:小明去銀行取錢,讀取到卡里有100元,然後小明將100元取出,但是資料還沒有提交到資料庫中;          這個時候小紅拿著同一張卡去取錢,因為小明的取出的100元還沒有被寫到資料庫,小紅讀到的還是100            元,小紅讀到的就是小明沒有提交的資料,這就是髒讀。

                2、不可重複讀: 事務 讀取到了 另一個事務已經提交的資料。 針對update

                   有些人會問,這不是問題,正確的做法不就是要讀取到已經提交的資料嗎,但有些情況是隻需要讀取未提交的資料,所以這是個問題。

                    例如:由於經驗少,目前沒有遇到這種情況,但是肯定有,

                3、虛度、幻讀:事務 讀取到了 另一個事務已經提交的資料。 針對的是insert delete

               

 

              解決事務隔離性產生的問題

                1、讀未提交:解決O個問題,還有3個問題 這三個問題就是前面說的三個

                2、讀已提交:解決1個問題,還有2個問題,解決第一個問題,還有後面兩個問題

                3、可重複讀:一個事務讀到的還是原來的資料,即使另一個事務已經提交,解決2個問題,還有1個問題 解決前面兩個問題,還有最後一個問題

                4、序列化:單事務、兩個事務同時對一個內容進行操作,必須等待前一個事物操作完成,後一個事務才能進行操作。解決全部問題。

                

               mysql預設的隔離級別:可重複讀。  oracle預設的隔離級別:讀已提交

              

              丟失更新問題:

                   後一次更新將前一次更新的內容給覆蓋了,這就是丟失更新問題,

                    l  A 查詢資料,username = 'jack' ,password = '1234'l 

                       B 查詢資料,username="jack", password="1234"l 

                     A 更新使用者名稱 username="rose",password='1234'    -->   username="rose",password="1234"l 

                     B 更新密碼   password="9999" ,username="jack"  -->   username="jack",password='9999'  

                  第三句話:A將使用者名稱更新為rose  此時資料庫 username = rose password = 1234

                  第四句話:B將密碼改為9999 但使用者名稱還是jack 但是更新後,又把原資料庫中username的rose更新為jack了,密碼為9999

 

              解決:樂觀鎖和悲觀鎖

                樂觀鎖:丟失更新肯定不會發生,在資料庫中增加一個識別符號,比較版本號,如果一樣,修改版本自動+1.。如果不一樣,必須先查詢,再更新

                悲觀鎖:丟失更新肯定會發生:使用排他鎖和共享鎖

                      共享鎖:只能讀,不能寫。

                      排他鎖:只能一個進行寫,不能擁有其他鎖,也就是說,若事務T對資料物件A加上X鎖,則只允許T讀取和修改A,其他任何事務都不能再對A加任何型別的鎖,直到T釋放A上的鎖。這就保證了其他事務在T釋放A上的鎖之前不能再讀取和修改A

 

  

二、如何確保N個執行緒可以訪問N個資源同時又不導致死鎖?

      自我解答:  

            這題不會

      參考答案:

            使用多執行緒的時候,一種非常簡單的避免死鎖的方式就是:指定獲取鎖的順序,並強制執行緒按照指定的順序獲取鎖。因此,如果所有的執行緒都是以同樣的順序加鎖和釋放鎖,就不會出現死鎖了。

      自我評價:

            首先得知道死鎖的四個必要條件 

              (1) 互斥條件:一個資源每次只能被一個程式使用。
              (2) 請求與保持條件:一個程式因請求資源而阻塞時,對已獲得的資源保持不放。
              (3) 不剝奪條件:程式已獲得的資源,在末使用完之前,不能強行剝奪。
              (4) 迴圈等待條件:若干程式之間形成一種頭尾相接的迴圈等待資源關係。

                  解決死鎖的方式最簡單的就是讓最後一個條件不成立,按同樣的順序加鎖和釋放鎖

 

三、Java集合類框架的基本介面有哪些?

      自己解答:

            其實在寫的隨筆中,就有關於集合的總結,大概就三類介面、set、map、list

      參考答案:

           集合類介面指定了一組叫做元素的物件。集合類介面的每一種具體的實現類都可以選擇以它自己的方式對元素進行儲存和排序。有的集合類允許重複的鍵,有些不允許。
            Java集合類提供了一套設計良好的支援對一組物件進行操作的介面和類。Java集合類裡面最基本的介面有:
            Collection:代表一組物件,每一個物件都是它的子元素。
            Set:不包含重複元素的Collection。
            List:有順序的collection,並且可以包含重複元素。
            Map:可以把鍵(key)對映到值(value)的物件,鍵不能重複。 

 

       自我評價:

            1、set介面:不可重複,無序,實現類有HashSet、linkedset等。

            2、list介面:可重複,有順序,實現類有arrayList、linkedList等

            3、map介面:以鍵值對的形式來儲存資料,鍵不能重複,實現類有hashMap等,

              要看不同請看我寫的JavaSE集合的深入的一系列博文

 

四、為什麼集合類沒有實現Cloneable和Serializable介面?

       自我解答:

           這個不知道,Serializable介面稱為序列化介面,百度過,用來形成持久化物件用的,比如,將可序列化的物件存入到硬碟中。

 

      參考答案:

           克隆(cloning)或者是序列化(serialization)的語義和含義是跟具體的實現相關的。因此,應該由集合類的具體實現來決定如何被克隆或者是序列化

 

      自我評價:

           首先得明白Serializable介面乾嘛用的

           1、Serializable介面

              將物件的狀態儲存在儲存媒體中以便可以在以後重寫建立出完全相同的副本;

              按值將物件從一個從一個應用程式域發向另一個應用程式域。

            上面的官方解釋太難懂了,通俗的講,就是將物件轉換為位元組流後,還能從位元組流轉換成原來的物件,需要實現這樣的效果,就需要將物件類實現Serializable介面。

           2、cloning介面

              需要將物件克隆,也就是使用clone()方法時,就需要實現該介面

          明白了上面兩個概念,實現著兩個介面,是看具體的情況,並不是每個collection介面的實現類都需要使用上面的情況,所以只能根據具體的情況來決定是否實現Serializable介面和cloning介面。

 

      組織語言:    

            首先理解Serializable介面和cloning介面是幹什麼用的,Serializable介面是序列化介面,實現序列化介面的實現類就是使用位元組流傳輸,而實現cloning介面,是能夠克隆自己,使用clone()方法,而並不是所有的collection都需要用到上面兩種情況,所以不需要在collection上實現著兩個介面。

 

 

五、什麼是迭代器(Iterator)?

      自己解答:

            迭代器,就是用來迭代各種資料型別的,比如,取出陣列中的每個資料,取出集合中的每個資料,將不同儲存資料的型別用一個統一的方法來迭代出資料,這就是迭代器,為什麼需要迭代器,因為如果要取出陣列中的資料和要取出集合中的資料,他們要執行的程式碼不一樣, 不統一,所以就有了Iterator介面。就是為了解決這個問題。

    

      參考答案:

            Iterator介面提供了很多對集合元素進行迭代的方法。每一個集合類都包含了可以返回迭代器例項的

            迭代方法。迭代器可以在迭代的過程中刪除底層集合的元素,但是不可以直接呼叫集合的
            remove(Object Obj)刪除,可以通過迭代器的remove()方法刪除。

 

      自我評價:

            上面理解錯了,使用iterator是因為在不同的集合中,都能使用Iterator來迭代,而不用管集合是哪個,而其他類也想用iterator迭代的話,那麼就實現iterator介面,實現其中的方法,那麼也能按照Iterator定義的方法來迭代了,平常普通陣列就直接用for迴圈搞定啦,理解錯了,是因為看一篇部落格,講解為什麼有Iterator,迭代器設計模式時理解錯了,博文地址:http://shmilyaw-hotmail-com.iteye.com/blog/1469288   感覺還不錯這篇部落格,起碼讓我知道了為什麼使用Iterator,和它的設計。

           1、迭代器的使用

              實現了Iterator介面,使用方法iterator()要求容器返回一個Iterator,

                next():返回第一個元素

                hasNext():是否還有元素

                remove():將返回來的元素刪除。

              注意:不可以直接呼叫集合中的方法remove()來刪除元素,只能通過Iterator中的方法

            2、為什麼要有迭代器?

              上面其實已經分析過來,為了讓所有的集合都有統一的遍歷方式,不用管集合是什麼,迭代器統一了對容器的訪問方式,collection介面就已經繼承了Iterator介面,所以之下的所有collection介面實現類都已經實現了Iterator介面。

      

 

 

      

      

 

 

 

      

                 

相關文章