新建(New)、可運行(Runnable)、阻塞(Blocking)、無限期等待(Waiting)、有限期等待(Timed-Waiting)、死亡(Terminated)java
守護線程時提供通用服務的線程(例如垃圾回收線程),優先級很低
經過Thread對象的setDaemon(boolean)方法設置守護線程與用戶線程,注意此方法必須在線程對象的start方法以前調用,不然會拋出java.lang.IllegalThreadStateException異常
守護線程建立的線程默認是守護線程,用戶線程同理。
守護線程是爲了服務用戶線程而存在的,全部用戶線程結束以後,jvm就退出了,守護線程天然也結束,因此守護線程的結束時間不肯定數據庫
線程的sleep方法(靜態方法),休眠當前線程,當前線程進入timed-waiting狀態api
線程對象的yield方法代表該線程已經完成了最重要的工做,嘗試讓出cpu佔用,把cpu使用權讓給同優先級的其餘線程安全
經過調用線程對象的interrput方法中斷該線程,若是該線程處於等待/阻塞狀態,會拋出java.lang.InterruptedException異常。
該方法不能中斷處於I/O阻塞或synchronized阻塞的線程
線程對象的該方法被調用後,會設置阻斷標誌爲true,經過interrupted()方法檢查是否有人調用了本線程的interrupt方法多線程
檢查是否有人調用了本線程的interrupt方法併發
線程池的shutdownNow方法就是經過調用全部工做線程的interrupt方法來中斷工做線程jvm
https://www.cnblogs.com/darknessplus/p/10359256.htmlide
都是可重入鎖
synchronized關鍵字由jvm實現,ReentrantLock由jdk實現
ReentrantLock提供比synchronized更高級的功能性能
ThreadLocal類
ThreadLocal 不是用來協調多線程的,而是爲同一個線程的不一樣方法提供共享變量。
一個線程的ThreadLocal變量在任何方法內都是可見的
線程Thread保存了ThreadLocalMap,ThreadLocalMap保存了本線程的全部ThreadLocal數據
ThreadLocal提供的方法
public T get() { } public void set(T value) { } public void remove() { } protected T initialValue() { }
多線程協做解決問題時,須要對他們的執行順序進行協調
調用另外一個線程對象的join方法表示本線程等待另外一個線程執行完成後再繼續執行
wait、notify是Object類提供的final方法,不可重寫。
經過調用某個對象的wait方法,釋放本線程對該對象持有的鎖,進入阻塞狀態。
另外一個線程調用該對象的notify方法,喚醒該對象的鎖的阻塞隊列中的一個線程,notifyAll方法喚醒該對象的等待隊列的全部線程。
wait期間,線程會釋放鎖,否則會死鎖。
配合synchronized使用,再同步代碼中使用。
生產者消費者問題:
public class Wait { public static void main(String[] args) throws InterruptedException { LinkedList<Integer> list = new LinkedList<Integer>(); Factory factory = new Factory(); factory.setList(list); factory.setMaxSize(10); for(int i=1;i<=10;i++) { Producer producer = new Producer(); producer.setNum(i); producer.setFactory(factory); producer.start(); Consumer consumer = new Consumer(); consumer.setNum(i); consumer.setFactory(factory); consumer.start(); } } } class Producer extends Thread{ private AbstractFactory factory; private int num; public void setNum(int num) { this.num = num; } public void setFactory(AbstractFactory factory) { this.factory = factory; } @Override public void run() { factory.produce(num); } } class Consumer extends Thread{ private AbstractFactory factory; private int num; public void setFactory(AbstractFactory factory) { this.factory = factory; } public void setNum(int num) { this.num = num; } @Override public void run() { factory.consume(num); } } class Factory implements AbstractFactory{ private List<Integer> list; private int maxSize; public void setList(List<Integer> list) { this.list = list; } public void setMaxSize(int maxSize) { this.maxSize = maxSize; } public void produce(int num) { synchronized (list) { while(num+list.size()>maxSize) { try { System.out.println("倉庫已滿。要生產的"+num+",庫存容量"+maxSize); list.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } int size=list.size(); for(int i=size;i<size+num;i++) { list.add(i); } System.out.println("生產"+num+"件,總共"+list.size()+"件"); list.notifyAll(); } } public void consume(int num) { synchronized (list) { while(list.size()-num<0) { try { System.out.println("倉庫已空。要消費的"+num+",庫存容量"+list.size()); list.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } int size=list.size(); for(int i=size-1;i>=size-num;i--) { list.remove(i); } System.out.println("消耗"+num+"件,總共"+list.size()+"件"); list.notifyAll(); } } } interface AbstractFactory { void produce(int num); void consume(int num); }
對應着Object的wait和notify方法,Lock也有相似的機制。
經過Lock.newCondition()方法獲取一個condition對象,經過condition對象的await和signal方法進行線程同步。
在使用condition對象的await和signal方法以前必須得到重入鎖,調用signal方法後最好釋放重入鎖。
控制一個線程等待其餘線程
public static void main(String[] args) throws InterruptedException { final CountDownLatch count = new CountDownLatch(10); for(int i=0;i<10;i++){ new Thread(){ @Override public void run() { System.out.println(Thread.currentThread().getName()); count.countDown(); } }.start(); } count.await(); System.out.println("END"); }
輸出:
Thread-0 Thread-2 Thread-3 Thread-1 Thread-5 Thread-4 Thread-6 Thread-7 Thread-8 Thread-9 END
信號量,控制併發線程數
public static void main(String[] args) { Semaphore semaphore = new Semaphore(1); for (int i = 0; i < 10; i++) { new Thread() { @Override public void run() { try { semaphore.acquire(); System.out.println(Thread.currentThread().getName() + "正在運行"); Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } finally { System.out.println(Thread.currentThread().getName() + "結束"); semaphore.release(); } } }.start(); } }
輸出:
Thread-5正在運行 Thread-5結束 Thread-0正在運行 Thread-0結束 Thread-3正在運行 Thread-3結束 Thread-8正在運行 Thread-8結束 Thread-6正在運行 Thread-6結束 Thread-2正在運行 Thread-2結束 Thread-7正在運行 Thread-7結束 Thread-1正在運行 Thread-1結束 Thread-4正在運行 Thread-4結束 Thread-9正在運行 Thread-9結束
得到任務的返回值
阻塞隊列,在線程池裏有應用
對數據更新的衝突持保守態度,認爲總會發生衝突。策略是在處理數據時加鎖
樂觀鎖認爲發生衝突的狀況比較少,不加鎖,而是在更新數據的時候檢查是否發生了衝突。
爲數據庫表增長版本號字段,每次更新數據版本號+1。在修改數據前獲取版本號,提交修改時檢查兩次版本號是否一致,如不一致說明數據更新發生了衝突。
Compare And Swap
現值V、舊值A、新值B,當且僅當V==A,更新B到數據庫
硬件實現的原子操做
CAS,V==A並不能說明V沒有發生過改變
CAS適用讀多寫少,synchronized適用寫多(衝突多)