好比一個main方法裏面前後運行thread1,,thread2,thread3,那麼thread1.start()以後,運行thread1.join(),這是會讓主線程mian等待新的線程thread1執行完了,再執行主線程mian下面的代碼,thread1.join()是然主線程main wait。java
package com.java.yj; /** * Created by yejian on 2018/7/9. */ public class MultiThread { public static void main(String[] args) throws InterruptedException { Thread thread1 = new Thread(new Thread1()); thread1.start(); thread1.join(); Thread thread2 = new Thread(new Thread2()); thread2.start(); thread2.join(); Thread thread3 = new Thread(new Thread3()); thread3.start(); } public static class Thread1 implements Runnable{ @Override public void run() { System.out.println("Thread1"); } } public static class Thread2 implements Runnable{ @Override public void run() { System.out.println("Thread2"); } } public static class Thread3 implements Runnable{ @Override public void run() { System.out.println("Thread3"); } } }
java5之後提供的一個多線程操做方法,建立一個只有一個線程的線程池操做,會建立一個線程隊列,按FIFO的順序執行裏面的線程。編程
package com.java.yj; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; /** * Created by yejian on 2018/7/9. */ public class MultiThread2 { public static void main(String[] args) throws InterruptedException { ExecutorService executor = Executors.newSingleThreadExecutor(); executor.submit(new Thread1()); executor.submit(new Thread2()); executor.submit(new Thread3()); executor.shutdown(); } public static class Thread1 implements Runnable{ @Override public void run() { System.out.println("Thread1"); } } public static class Thread2 implements Runnable{ @Override public void run() { System.out.println("Thread2"); } } public static class Thread3 implements Runnable{ @Override public void run() { System.out.println("Thread3"); } } }
解決併發過程當中如何處理可見性,原子性,有序性的問題
runnable ,thread。
併發編程中的2個關鍵問題:緩存
a. 線程間如何通訊 --wait() notify() notifyAll()
a) 共享內存 -隱式通訊
b) 消息傳遞 - 顯示通訊多線程
b. 線程之間如何同步
在共享內存的併發模型中,同步是顯示作的; synchronized
在消息傳遞的併發模型中,因爲小時發送必須在消息接受以前,因此同步是隱式的併發
什麼對象是內存共享的 ,什麼不是,堆內存的對象,java虛擬機棧
JMM定義了線程和主內存之間的一個關係。線程之間通信,必須經過主內存通信。jvm
volatile、synchronized
volatile 功能,聲明瞭volatile的變量,進行寫操做的時候,jvm會向處理器發送一條Lock的前綴指令,會把這個變量所在緩存行的數據寫回到系統內存。
在多處理器的狀況下,保證各個處理器緩存一致性的特色,會實現緩存一致性協議。改變了值的volatile變量,在其餘行程被指爲失效狀態其餘線程要使用這個變量,須要從新到駐村裏面去取。ide
synchronized:可重入鎖、互斥性、可見性
volatile 能夠作到原子性,可見性,不能作到複合操做的原子性性能
好比: volatile int i;
i++ 讀取i的值,給i加1,把新的值賦值給i,這個i++操做在多線程環境下是沒法保證原子性的優化
synchronized後面鎖定的對象,能夠是一個類對象,也能夠是一個成員變量。
第一個線程進來調用monitorener 和monitorexit實現,獲取對象的監視器,釋放對象監視器
後續進程過來,若是monitor尚未釋放,那麼他獲取不到這個對象的monitor,會放到一個對列裏面:synthronizedQueue。 等到對象的鎖釋放了,通知synthronizedQueue出隊列,獲取那個monitor。線程
Lock是java5之後出現的,在juc包: java.util.concurrentlocks
1.1 獲取鎖的線程執行完了該代碼塊 1.2 線程出現異常
2.1 讀寫衝突
ReadWriteLock
ReadLock
WriteLock
ReenterantLock可重入鎖
可中斷鎖
公平鎖 等待一個鎖的實際越長,獲取這個鎖的概率越高
ReenterantReadWriteLock 可重入讀寫鎖
Lock是java裏面的一個接口,有豐富的實現,而synchronized是java的一個關鍵字,是一個內置的功能
競爭資源激烈的狀況,Lock性能優於synchronized,可是jdk7,8對synchronized作了不少優化,性能差別不大。