在此總結下自己在面試過程中面試官問的問題,以便於以後查閱:
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++這種形式下便無法保證其原子性。