一、泛型出現以前存在的問題:緩存
全部對象的類型都繼承自Object,虛擬機只有到運行時才能知道這個Object具體是什麼類型,在編譯期是沒法檢查這個Object是否強制轉型成功,會將ClassCaseException的風險轉移到程序運行期。多線程
二、泛型的做用:架構
經過泛型,編譯器能夠在編譯階段發現類型不一致的問題併發
三、泛型擦除:ide
將Java代碼編譯成Class文件,經過反編譯發現泛型都不見了,被替換爲原生類型,並插入強制轉型的代碼。學習
//泛型擦除前 List<String> list = new ArrayList<>(); list.add("hello"); System.out.println(list.get(0)); //泛型擦除後 List list1 = new ArrayList(); list1.add("hello"); System.out.println((String) list1.get(0)); 複製代碼
一、公共子表達式消除 在程序基本塊中,若是一個表達式E已經被計算過了,下次再次使用的時候,若是表達式的變量值都沒發生改變,就能夠直接拿表達式的結果來代替E。優化
int x = 1; int y = 2; int z = x + y; int w1 = x + y +2; //編譯器對公共子表達式(x+y)進行消除 int w2 = z + 2; 複製代碼
類加載解析節點,將一部分符號引用轉化爲直接引用。前提是程序運行前有可肯定的調用版本,而且在運行期不可變。這些編譯期可知、運行期不可變的方法調用就是解析。線程
一、靜態分派:3d
根據靜態類型來定位方法的分派叫作靜態分派,發生在編譯階段。對象
//父類 public class Parent { } //子類 public class Son extends Parent { } //調用 public class MyTest { public void say(Parent parent) { System.out.println("parent say"); } public void say(Son son) { System.out.println("son say"); } public static void main(String[] args) { MyTest myTest = new MyTest(); //實際類型爲Parent Parent parent = new Parent(); //實際類型爲Son Parent son = new Son(); myTest.say(parent); myTest.say(son); } } 複製代碼
返回結果:
Parent爲變量的靜態類型,Son爲實際類型。其中靜態類型是在編譯期可知的,而實際類型是在運行期肯定下來的,編譯器在編譯階段不知道某個對象的實際類型是什麼,因此是用靜態類型做爲斷定依據來選擇使用哪一個重載版本的,因此選擇了say(Parent)做爲調用目標。
二、動態分派
public class Parent { public void say() { System.out.println("parent...."); } } public class Son extends Parent { public void say() { System.out.println("son...."); } } //調用 Parent parent = new Parent(); Parent son = new Son(); parent.say(); son.say(); 複製代碼
結果:
虛擬機根據實際類型的不一樣來分派方法
基本步驟:
將變量從主內存拷貝到工做內存中,將工做內存同步到主內存中。定義了8中操做,每步操做都是原子的、不可再分。
注 :
一、可見性:
private volatile static int x; public static void main(String[] args) { for (int i = 0; i < 20; i++) { Thread thread = new Thread(new Runnable() { @Override public void run() { for (int i1 = 0; i1 < 1000; i1++) { x++; } } }); thread.start(); } System.out.println("x="+x); } 複製代碼
最終的結果不是20000,說明volatile修飾的變量也沒實現正確併發的目的。
緣由:
x++ 是由多條字節碼指令構成的,包括取值,+1,賦值操做,volatile只能保證最後變量取到操做棧頂時該變量的同步性,可是在這以前其餘線程是能夠修改該變量的值。
二、volatile適用的場景:
三、禁止指令重排序優化 普通變量只能保證執行過程全部依賴賦值結果的地方都能獲得正確的結果,不能保證變量賦值的順序與代碼中執行順序一致,
實現方式:在多線程訪問同一內存時,至關於經過一個內存屏障,保證不能把後面的指令重排序到內存屏障以前的位置。