Java常考面試題(四)


一、什么是死鎖(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接口。

      

 

 

      

      

 

 

 

      

                 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM