參考:
https://github.com/chengbingh...java
進程是線程的容器
線程狀態圖:git
2.2 線程的基本操做
2.2.1新建線程
2.2.2終止線程
stop 暴力終止線程,廢棄方法github
2.2.3線程中斷
方法:多線程
2.2.4 等待(wait)和喚醒notify
注意:
wait 是object的一個方法,調用wait方法的對象,必須在synchronized 中,由於要獲取它的監視器。
wait會釋放鎖併發
public class SimpleWN { final static Object obj = new Object(); public static void main(String[] args) { Thread t1 = new Thread(new Runnable() { @Override public void run() { synchronized(obj) { System.out.println("t1.start,and t1 will wait"); try { // 調用wait 方法的這個對象必須被synchronizeed //wait 會釋放鎖 obj.wait(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("t1 was notify"); } } }); Thread t2 = new Thread(new Runnable() { @Override public void run() { synchronized(obj){ System.out.println("t2 start and will notify t1"); // 調用notify 方法的這個對象必須被synchronizeed //若是 有n個線程此時都是因爲調用了obj.wait方法,那麼會喚醒任意一個 obj.notify(); try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("t2 end run"); } } }); t1.start(); t2.start(); } }
輸出:注意鎖 t1.start,and t1 will wait t2 start and will notify t1 t2 end run t1 was notify
2.2.5 掛起(suspend)和繼續執行(resume)
suspend()和resume方法ide
2.2.6 join 和yeild
join:加入,把線程當作一個方法了。
yeild:讓出線程執行權,可是仍是會爭奪線程的執行權優化
JMM: 原子性,可見性,有序性
原子性:32位虛擬機中多線程讀寫long不會有問題,可是不能保證i++spa
可見性:
虛擬機在-server模式下會進行優化,下面的程序永遠不會跳出。線程
/** * @author ChengBing Han * @date 9:39 2018/6/22 * @description */ public class NoVisibility { private static boolean ready; private static int number; private static class ReaderThread extends Thread { public void run() { /* while (!ready){ System.out.println(new Date()); }*/ //這個和上述的優化不一樣,這個在-server模式下會優化 while (!ready) ; System.out.println(number); } } public static void main(String[] args) throws InterruptedException { //永遠不會終止程序 new ReaderThread().start(); Thread.sleep(1000); number = 42; ready = true; Thread.sleep(2000); } }
備註:上述ready 用volatile 修飾後就會退出,或者用-client 模式啓動虛擬機code
1-10,優先級逐漸升高
2.7 synchronized(內部鎖)
volatile 能夠保證原子性,和可見性,可是若是兩個線程同時修改了某個變量,那麼仍是沒法識別的,這時volatile的侷限性。因此須要synchronized等來確保
2.8.1 沒有提示的錯誤e
好比兩個正數int 相加, 溢出致使 其值爲負數。
2.8.2 併發下的ArrayList
兩個線程同時對一個ArrayList add 對象,每一個線程add 10000 個對象, 最終結果
可能1:ArrayList 中有2萬個對象。
可能2:拋出異常
ArrayList 內部結構被破壞了
可能3:ArrayList 中的對象個數小於2萬
2.8.3 併發下的HashMap
兩個線程同時對HashMap添加對象,每一個線程add 10000 個對象,最終結果
可能1:HashMap 中有2萬個對象。
可能2:對象個數少於2萬
可能3:HashMap內部結構發生破壞,程序沒法終止,cpu會被大量消耗。
2.8.4 錯誤加鎖
static Integer i = 0; ......... synchronized(i){ i++; } //問題在於, integer是不可變的,因此每次i++都會建立一個新的對象。能夠用javap 反編譯查看
容許多個線程同時訪問:信號量
容許幾個線程訪問