多線程的一些心得

在此總結下自己在面試過程中面試官問的問題,以便於以後查閱:

1.談談你對java中hashMap的認識。

     hashMap是java中自帶的一個類,其作用爲存儲key-value形式的數據,key、value都可爲泛型。其key值允許有一個有null,其value值可爲null。hashMap的初始size爲16,負載因子爲0.75,如果數據的個數超過16 * 0.75時就會自動進行擴容操作。

    hashMap的查找時間複雜度理想情況是O(1),但在日常業務中可能會出現哈希碰撞。hash碰撞的意思是兩個不同的key在經過hash()之後得到了一樣的hashCode,這時候hashMap的處理方式是將其放在該hashCode對應的bocket中,而這兩個元素就已鏈表的形式憑藉在一起,這更進一步的印證了hashMap數組 + 雙向列表的結構。

     在取值的時候也是一樣,先根據hashCode定位到指定的bocket,如果有hash衝突再用equals()方法來比較key從而取到目標的key-value。

     1.7和1.8的區別是1.8在1.7的基礎上將鏈表結構在滿足一定條件下修改爲紅黑樹的結構,一旦這條件不滿足紅又會自動調整爲鏈表結構。

 

 2.你對多線程瞭解嗎?談談線程的幾個狀態。

   首先我們點進入thread裏面,裏面有線程的state

* <ul>
* <li>{@link #NEW}<br>
*     A thread that has not yet started is in this state.
*     </li>
* <li>{@link #RUNNABLE}<br>
*     A thread executing in the Java virtual machine is in this state.
*     </li>
* <li>{@link #BLOCKED}<br>
*     A thread that is blocked waiting for a monitor lock
*     is in this state.
*     </li>
* <li>{@link #WAITING}<br>
*     A thread that is waiting indefinitely for another thread to
*     perform a particular action is in this state.
*     </li>
* <li>{@link #TIMED_WAITING}<br>
*     A thread that is waiting for another thread to perform an action
*     for up to a specified waiting time is in this state.
*     </li>
* <li>{@link #TERMINATED}<br>
*     A thread that has exited is in this state.
*     </li>
* </ul>

         NEW新建狀態,剛剛創建線程,此時線程並沒有運行

         RUNNABLE:運行狀態,此時的線程在Java虛擬機裏面運行。

         BLOCKED:阻塞狀態,此時線程進入等待狀態,放棄了CPU的使用權。

         WAITING:等待狀態,線程處於等待狀態。

         TIMED_WAITING:等待超時狀態,超時以後自動返回。

         TERMINATED:線程終止狀態。     

這裏有一個需要注意的地方,如果是繼承Thread的話,啓動了thread.start(),此時線程並沒用處於運行狀態,當cpu分給線程資源的時候纔算是真正的出入執行狀態。

 

3.我想順序輸出A.B.C三個線程,該如何處理呢?

      (1).如果是使用繼承Thread,那麼直接使用其中自帶的一個方法join();

如下:

public final synchronized void join(long millis)
throws InterruptedException {
    long base = System.currentTimeMillis();
    long now = 0;

    if (millis < 0) {
        throw new IllegalArgumentException("timeout value is negative");
    }

    if (millis == 0) {
        while (isAlive()) {
            wait(0);
        }
    } else {
        while (isAlive()) {
            long delay = millis - now;
            if (delay <= 0) {
                break;
            }
            wait(delay);
            now = System.currentTimeMillis() - base;
        }
    }
}

   thread.join()是被final and synchronized 修飾的,因此如果線程如果要保持相關順序行的話直接使用join()方法便能保證!如果不設置millis,則後面的thread就會一直等待,知道前面的thread執行完成才能夠執行。如果設置了millis的話,那麼在執行時間等於這個值之後,就會開始執行下一個線程。

Demo:

public class Demo {
    public static void main(String[] args) {

        for(int i = 0;i < 100;i ++){
            Thread t3 = new NewThread("線程3");
            Thread t1 = new NewThread("線程1");
            Thread t2 = new NewThread("線程2");
            try{
                t1.start();
                t1.join();
                t2.start();
                t2.join();
                t3.start();
                t3.join();
            }catch (Exception e){
                System.out.println(e);
            }
        }
    }
}

 4.volatile關鍵字的作用是什麼?

    volatile是一個類型修飾符,其修飾的對象在多線程操作下保證了對象的可見性。在編譯器和處理器對class文件進行編譯或者預處理的時候,爲了提高效率往往會多指令進行重排序。使用了volatile關鍵字修飾之後就禁止對指令進行重排序,這便是volatile的另一個特性:有序性。如果是在單個線程的讀/寫下,能夠保證其原子性,但是如果是i++這種形式下便無法保證其原子性。

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章