JAVA小知識點記錄(三)

HashMap、Hashtable、ConccurentHashMap三者的區別
HashMap線程不安全,數組+鏈表+紅黑樹
Hashtable線程安全,鎖住整個對象,數組+鏈表
ConccurentHashMap線程安全,CAS+同步鎖,數組+鏈表+紅黑樹
HashMap的key,value均可爲null,其他兩個不行。

在JDK1.7和JDK1.8中的區別
在JDK1.8主要設計上的改進有以下幾點:

1、不採用segment而採用node,鎖住node來實現減小鎖粒度。
2、設計了MOVED狀態 當resize的中過程中 線程2還在put數據,線程2會幫助resize。
3、使用3個CAS操作來確保node的一些操作的原子性,這種方式代替了鎖。
4、sizeCtl的不同值來代表不同含義,起到了控制的作用。
採用synchronized而不是ReentrantLock

詳細關於ConcurrentHashMap同步原理 https://www.jianshu.com/p/5dbaa6707017

重載方法只有參數類型不同,且爲父子類,調用選擇的時候並不是按照實例類型,而是按照引用類型,強轉和經過另一個函數的過濾都會導致在選擇進入哪個函數的結果發生變化

擴展:在groovy中,方法的調用是在運行時被選擇。這被稱爲運行時調度和多方法。根據運行時參數類型選擇方法。
在java中,這個是相反的,在編譯時,根據定義的類型, 選擇方法。
以下代碼以Java代碼的形式編寫,可以在Java和Groovy中編譯,但其行爲會有所不同:

int method(String arg) {
return 1;
}
int method(Object arg) {
return 2;
}
Object o = "Object";
int result = method(o);

在java中 result的值是2,
在groovy中的值是1
java使用的是靜態信息類型,o被聲明爲Object;然而groovy是在運行時選擇,這個方法真正被調用的時候。因爲o是一個String所以調運String的版本。

  1. volatile 修飾Int 屬性變量,能否保證int 屬性多線程 自增現成同步呢?
    順帶說下volatile關鍵字很重要的兩個特性:

保證變量在線程間可見,對volatile變量所有的寫操作都能立即反應到其他線程中,換句話說,volatile變量在各個線程中是一致的(得益於java內存模型—"先行發生原則");

2、禁止指令的重排序優化;

那麼換成volatile修飾count變量後,會有什麼效果呢? 試一試:

public class AtomicIntegerTest {

private static final int THREADS_CONUT = 20;
public static volatile int count = 0;

public static void increase() {
    count++;
}

public static void main(String[] args) {
    Thread[] threads = new Thread[THREADS_CONUT];
    for (int i = 0; i < THREADS_CONUT; i++) {
        threads[i] = new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 1000; i++) {
                    increase();
                }
            }
        });
        threads[i].start();
    }

    while (Thread.activeCount() > 1) {
        Thread.yield();
    }
    System.out.println(count);
}

}
結果似乎又失望了,測試結果和上面的一致,每次都是輸出小於20000的數字。這又是爲什麼麼? 上面的論據是正確的,也就是上面標紅的內容,但是這個論據並不能得出"基於volatile變量的運算在併發下是安全的"這個結論,因爲核心點在於java裏的運算(比如自增)並不是原子性的。

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