天天看點

Java常考面試題(三)

    序言

       說說今天遇到的一件小事吧,在遇到問題,查找答案時,看到很多人的部落格裡面都有提到關鍵字眼,可讓人覺得可恨的是,大多數人寫的博文中,基本上都是照着書上的語言發表的,看了跟沒看一樣,沒有一點通俗的語言和自己關于該知識點的講解,也有可能是覺得太簡單,不用做解釋,但是個人感覺,寫博文,在一些自己都需要思考一段時間去了解的東西,應該把自己思考的過程,如何了解的寫下來,而不是就把精華的部分複制黏貼上去,個人感覺沒什麼用,回想一下再寫計算機網絡教程學習曆程的博文中,自己也有類似的情況,應該改正過來,在乎的是每篇博文的品質,而不是數量,不能有那種拼命往上面怼文章,來顯示自己寫了很多東西,以此用來面試,我覺得更是無用,寫博文不為别人,是為了鞏固我們的知識,和發表自己對一些問題的見解,這樣才能真正的幫助到自己。開始今天的五題面試吧。

                                                                                ----WZY

一、程序和線程的差別是什麼?

      自己講解:

          程序:拿電腦來說,在電腦上背景運作了很多程式,那就是程序

          線程:為了完成一個程式的運作,可能程式中還有很多分支在一起運作共同來完成這個程式,分支的運作就是線程

            也就是說:程序中包括很多線程,

      參考答案:

          程序是執行着的應用程式,而線程是程序内部的一個執行序列。一個程序可以有多個線程。線程又叫做輕量級程序。

      自我評價:

          大概了解,但是語言描述的不好,應用程式下有很多執行序列。 不應該說分支。

          1、程序:執行的應用程式,通俗一點,在打開電腦的任務管理器中,就有很多應用程式,也就是程序

          2、線程:程序内部的一個執行序列,通俗的講,就是一個程式的運作,有很多線程在同時執行來共同維護該程序的運作

二、建立線程有幾種不同的方式?你喜歡哪一種?為什麼?

      自己解答:

          好久不用線程,這題直接不會了,哈哈,

          有三種方式可以用來建立線程:

            繼承Thread類

            實作Runnable接口

            應用程式可以使用Executor架構來建立線程池

            實作Runnable接口這種方式更受歡迎,因為這不需要繼承Thread類。在應用設計中已經繼承了别的對象的情況下,這需要多繼承(而Java不支援多繼承),隻能實作接口。同時,           線程池也是非常高效的,很容易實作和使用。

            隔得比較久,但是印象中也是隻有兩種建立線程的方式,一個是繼承,一個是實作接口。

            1、繼承Thread類,重寫run方法,在run方法中寫該線程要執行的任務,然後再在要執行該線程時,new出對象來,對象.start(),啟動該線程

            2、實作Runnable接口,實作其中的run方法,new出該對象A來,Thread thread = new Thread(A); 這樣,thread.start(),就能啟動該線程。

              注意:繼承Thread類局限于單繼承,是以實作Runnable接口,就能在繼承别的類。其實本質都一樣,Thread類也實作了Runnable接口。

            3、使用executor架構來建立多線程。可以自行百度去了解一下。

三、概括的解釋下線程的幾種可用狀态。

      自我解答:

            建立狀态、運作狀态、暫停狀态、死亡狀态         

     

           1. 建立( new ):新建立了一個線程對象。

           2. 可運作( runnable ):線程對象建立後,其他線程(比如 main 線程)調用了該對象 的 start ()方法。該狀态的線程位于可運作線程池中,等待被線程排程選中,獲 取 cpu 的使用權 。

           3. 運作( running ):可運作狀态( runnable )的線程獲得了 cpu 時間片( timeslice ) ,執行程式代碼。

           4. 阻塞( block ):阻塞狀态是指線程因為某種原因放棄了 cpu 使用權,也即讓出了 cpu timeslice ,暫時停止運作。直到線程進入可運作( runnable )狀态,才有 機會再次獲得 cpu timeslice 轉到運作( running )狀态。阻塞的情況分三種:

             (一). 等待阻塞:運作( running )的線程執行 o . wait ()方法, JVM 會把該線程放 入等待隊列( waitting queue )中。

             (二). 同步阻塞:運作( running )的線程在擷取對象的同步鎖時,若該同步鎖 被别的線程占用,則 JVM 會把該線程放入鎖池( lock pool )中。

             (三). 其他阻塞: 運作( running )的線程執行 Thread . sleep ( long ms )或 t . join ()方法,或者發出了 I / O 請求時, JVM 會把該線程置為阻塞狀态。 當 sleep ()            狀态逾時、 join ()等待線程終止或者逾時、或者 I / O 處理完畢時,線程重新轉入可運作( runnable )狀态。

           5. 死亡( dead ):線程 run ()、 main () 方法執行結束,或者因異常退出了 run ()方法,則該線程結束生命周期。死亡的線程不可再次複生。

                   

     自我評價:不清清楚這個内容,

           1、五個狀态 建立狀态 -- 可運作狀态 -- 運作狀态 -- 阻塞狀态 -- 銷毀狀态

            2、阻塞狀态

                等待阻塞:使用wait(),然後再等待隊列裡面呆着。等待依次被調用

                同步阻塞:調用了某個帶鎖的方法,目前鎖被其他線程給拿到了,就需要等待其他線程用完,然後再拿到該鎖,

                其他阻塞:比如 執行了 sleep、或者 join 方法,使之線程進入了睡眠或者要等待别的線程執行完才輪到自己。

四、同步方法和同步代碼塊的差別是什麼?

       自我解答:

            這個也不清楚。

       參考答案:

            差別:

              同步方法預設用this或者目前類class對象作為鎖;

              同步代碼塊可以選擇以什麼來加鎖,比同步方法要更細顆粒度,我們可以選擇隻同步會發生同步問題的部分代碼而不是整個方法;

       自我評價:

            1、同步的單詞是: synchronized 異步的單詞是: asynchronized

            2、同步方法和同步代碼塊隻得是用synchronized關鍵字對方法加鎖,

            3、同步方法: synbhronized隻對方法加鎖,作用的範圍就是,如果該類對象調用了該方法,則獲得鎖,其他線程不管是調用該帶鎖的方法還是非鎖方法都必須等待

            4、同步代碼塊:對方法或者任意代碼加鎖,不同的是,隻對獲得該段代碼的鎖機制生效,意思就是,當A線程獲得了該段代碼的鎖,B線程照樣執行其他非帶鎖的方法。

五、在螢幕(Monitor)内部,是如何做線程同步的?程式應該做哪種級别的同步?

            幾個多線程的題目頓時懵逼了,多線程這塊很弱,記不住,以前看了一點,都差不多忘記了。

        參考答案:

            螢幕和鎖在Java虛拟機中是一塊使用的。螢幕監視一塊同步代碼塊,確定一次隻有一個線程執行同步代碼塊。每一個螢幕都和一個對象引用相關聯。線程在擷取鎖之前不允許執行同步代碼。

            在 java 虛拟機中, 每個對象( Object 和 class )通過某種邏輯關聯螢幕,每個螢幕和一個對象引用相關聯, 為了實作螢幕的互斥功能, 每個對象都關聯着一把鎖. 一旦方法或者代碼塊被 synchronized 修飾, 那麼這個部分就放入了螢幕的監視區域, 確定一次隻能有一個線程執行該部分的代碼, 線程在擷取鎖之前不允許執行該部分的代碼 另外 java 還提供了顯式螢幕( Lock )和隐式螢幕( synchronized )兩種鎖方案

  

            1、有關于java虛拟機的一部分,在講解如何實作鎖機制的。這個感覺有點超出我自己的能力了,等看到了應該會知道,現在當時了解一下,有這個東西。