概 述
1. 多線程同步相關java封裝類:java.util.concurrent.locks. 包下;
1)線程的生命周期:初始化、就緒、運行、阻塞、死亡
2)Java中對線程定義的6種狀態:NEW、RUNNABLE、BLOCKED、WAITING、TIMED_WAITING、TERMINATED
3)線程的狀態轉換過程
從 NEW到 RUNNABLE狀態
NEW狀態的線程,不會被操作系統調度,因此不會執行。Java線程要執行,就必須轉換到 RUNNABLE狀態。從NEW轉到RUNNABLE狀態,只要調用線程對象的start()方法就可以了。
從 RUNNABLE 到 TERMINATED 狀態
線程執行完run()方法后,會自動轉換到 TERMINATED 狀態;當然如果執行run()方法的時候異常拋出,也會導致線程終止;有時我們需要強制中斷run()方法的執行,例如run()方法訪問一個很慢的網絡,我們想終止怎么辦呢?Java的Thread類里面有個stop()方法,不過已經標記為 @Deprecated,所以不建議使用了。正確的姿勢其實是調用interrupt()方法。
stop()方法會真的殺死線程,不給線程喘息的機會,如果線程持有 ReentrantLock 鎖,被 stop() 的線程並不會自動調用ReentrantLock的unlock()去釋放鎖,那其他線程就再也沒機會獲得 ReentrantLock 鎖,這實在是太危險了。所以該方法就不建議使用了,類似的方法還有 suspend() 和 resume() 方法,這兩個方法同樣也都不建議使用了,所以這里也就不多介紹了。
而interrupt() 方法就溫柔多了,interrupt()方法僅僅是通知線程,線程有機會執行一些后續操作,同時也可以無視這個通知。被interrupt的線程,是怎么收到通知的呢?一種是異常,另一種是主動檢測。
2. 關於Lock接口
1)獲取鎖
lock() 無返回值
tryLock() 有返回值
tryLock(long time, TimeUnit unit) 在一定時間內獲取鎖
lockInterruptibly() 未獲取到鎖,會響應中斷(拋出異常)
2)釋放鎖
unLock()
3)實現類
ReentrantLock: 可重入鎖 唯一實現Lock接口
3. 關於ReadWriteLock(讀寫鎖)接口
如果有一個線程已經占用了讀鎖,則此時其他線程要申請讀鎖,也可以同時獲取到讀鎖。
如果有一個線程已經占用了讀鎖,則此時其他線程如果要申請寫鎖,則申請寫鎖的線程會一直等待釋放讀鎖。
如果有一個線程已經占用了寫鎖,則此時其他線程如果申請寫鎖或者讀鎖,則申請的線程會一直等待釋放寫鎖。
1)獲取鎖
readLock() 獲取讀鎖
writeLock() 獲取寫鎖
2)釋放鎖
readLock().unLock() 釋放讀鎖
writeLock().unLock() 釋放寫鎖
3)實現類
ReentrantReadWriteLock: 可重入鎖 唯一實現Lock接口
4. 相關概念
1). 可重入鎖
如果鎖具備可重入性,則稱作為可重入鎖。像synchronized和ReentrantLock都是可重入鎖,
可重入性實際上表明了鎖的分配機制:基於線程的分配,而不是基於方法調用的分配。
舉個簡單的例子,當一個線程執行到某個synchronized方法時,比如說method1,而在method1中會調用另外一個synchronized方法method2,此時線程不必重新去申請鎖,而是可以直接執行方法method2。
簡單的理解:線程已經具備鎖,不必再申請鎖,可一直執行完畢。
2). 可中斷鎖
在Java中,synchronized就不是可中斷鎖,而Lock是可中斷鎖。
3). 公平鎖
公平鎖即盡量以請求鎖的順序來獲取鎖。
synchronized就是非公平鎖,它無法保證等待的線程獲取鎖的順序。
而對於ReentrantLock和ReentrantReadWriteLock,它默認情況下是非公平鎖,但是可以設置為公平鎖。
ReentrantLock中靜態內部類:1)NotFairSync實現非公平鎖;2)FairSync實現公平鎖
ReentrantLock lock = new ReentrantLock(true); 參數為true表示為公平鎖,為fasle為非公平鎖
4). 讀寫鎖
正因為有了讀寫鎖,才使得多個線程之間的讀操作不會發生沖突。
ReadWriteLock就是讀寫鎖,它是一個接口,ReentrantReadWriteLock實現了這個接口。
可以通過readLock()獲取讀鎖,通過writeLock()獲取寫鎖。
5. Lock和synchronized的區別
1)Lock是一個接口,而synchronized是Java中的關鍵字,synchronized是內置的語言實現;
2)synchronized在發生異常時,會自動釋放線程占有的鎖,因此不會導致死鎖現象發生;
而Lock在發生異常時,如果沒有主動通過unLock()去釋放鎖,則很可能造成死鎖現象,
因此使用Lock時需要在finally塊中釋放鎖;
3)Lock可以讓等待鎖的線程響應中斷,而synchronized卻不行,使用synchronized時,
等待的線程會一直等待下去,不能夠響應中斷;
4)通過Lock可以知道有沒有成功獲取鎖,而synchronized卻無法辦到。
5)Lock可以提高多個線程進行讀操作的效率。
在性能上來說,如果競爭資源不激烈,兩者的性能是差不多的,而當競爭資源非常激烈時(即有大量線程同時競爭),
此時Lock的性能要遠遠優於synchronized。所以說,在具體使用時要根據適當情況選擇。
6. Object下的鎖:
wait():釋放占有的對象鎖
notify(): 該方法會喚醒因為調用對象的wait()而等待的線程
notifyAll()則是喚醒所有等待的線程
一、 java多線程同步:synchronized及wait()、notify()
1 import java.util.Random; 2 import java.util.concurrent.*; 3 4 public class MyProductAndConsume { 5 6 volatile static int NUM = 1; 7 8 AtomicInteger atomicInteger = new AtomicInteger(0); 9 10 final Object productLock = Object.class; 11 final Object consumeLock = int[].class; 12 final ReentrantLock lock = new ReentrantLock(); 13 14 final class MyWorkProduct implements Callable { 15 public Object call() throws Exception{ 16 while (true) { 17 Thread.sleep(500); 18 synchronized (atomicInteger) { 19 while (atomicInteger.get() >= 1) //已有生產的產品(while是為了同時只能一個生產者工作) 20 atomicInteger.wait(); //阻塞當前線程 21 System.out.println(Thread.currentThread().getName() + "-MyWorkProduct : " + ++NUM); 22 atomicInteger.incrementAndGet(); 23 atomicInteger.notifyAll(); 24 } 25 } 26 } 27 } 28 29 final class MyWorkConsume implements Callable { 30 public Object call() throws Exception{ 31 while (true) { 32 Thread.sleep(new Random().nextInt(8000) + 500); 33 synchronized (atomicInteger) { 34 while (atomicInteger.get() <= 0) //無可消費產品(while是為了同時只能一個消費者消費) 35 atomicInteger.wait(); 36 System.out.println(Thread.currentThread().getName() + "-MyWorkConsume : " + NUM); 37 atomicInteger.getAndDecrement(); 38 atomicInteger.notifyAll(); 39 } 40 } 41 } 42 } 43 44 public void execute() { 45 ExecutorService executorService = Executors.newFixedThreadPool(5); 46 executorService.submit(new MyWorkProduct());executorService.submit(new MyWorkProduct()); 47 executorService.submit(new MyWorkConsume());executorService.submit(new MyWorkConsume());executorService.submit(new MyWorkConsume()); 48 } 49 50 public static void main(String[] args) { 51 new MyProductAndConsume().execute(); 52 } 53 }
運行結果:
pool-1-thread-2-MyWorkProduct : 2
pool-1-thread-3-MyWorkConsume : 2
pool-1-thread-2-MyWorkProduct : 3
pool-1-thread-4-MyWorkConsume : 3
pool-1-thread-1-MyWorkProduct : 4
pool-1-thread-5-MyWorkConsume : 4
pool-1-thread-1-MyWorkProduct : 5
pool-1-thread-3-MyWorkConsume : 5
pool-1-thread-1-MyWorkProduct : 6
pool-1-thread-5-MyWorkConsume : 6
pool-1-thread-2-MyWorkProduct : 7
pool-1-thread-4-MyWorkConsume : 7
pool-1-thread-1-MyWorkProduct : 8
pool-1-thread-4-MyWorkConsume : 8
pool-1-thread-1-MyWorkProduct : 9
pool-1-thread-4-MyWorkConsume : 9
pool-1-thread-1-MyWorkProduct : 10
pool-1-thread-3-MyWorkConsume : 10 …………
示例二:
1 package com.cheng2839.test; 2 3 import com.cheng2839.util.Logger; 4 5 /** 6 * java多線程同步 7 * 1. synchronized修飾方法[參見syncFunOne] 8 * 2. synchronized同步塊(普通類成員變量)[參見syncFunTwo] 9 * 3. synchronized同步塊(static類成員變量)[參見syncFunThree] 10 * 4. wait()及notify()的用法[參見syncFunFour1、syncFunFour2] 11 * 12 * @author cheng2839 13 * @date 2018年11月16日 14 */ 15 public class MyThreadTest001 { 16 17 //此處定義一個靜態類成員變量,供所有線程共用[共用信號量] 18 public static int NUM; 19 20 //Object成員變量 21 private Object lock = new Object(); 22 23 //Object靜態類成員變量 24 private static final Object LOCK = new Object(); 25 26 //初始化信號量值 27 public MyThreadTest001() { 28 NUM = 1; 29 } 30 31 /** 32 * synchronize修飾的方法,表示該方法是同步的 33 */ 34 public synchronized void syncFunOne() { 35 Logger.info(Thread.currentThread()+" - syncFunOne before : " + NUM); 36 NUM++; 37 Logger.info(Thread.currentThread()+" - syncFunOne after : " + NUM); 38 } 39 40 /** 41 * synchronize修飾的代碼塊,表示該方法中被synchronized修飾的代碼塊是同步的 42 */ 43 public void syncFunTwo() { 44 synchronized(lock) { 45 Logger.info(Thread.currentThread()+" - syncFunTwo before : " + NUM); 46 NUM++; 47 Logger.info(Thread.currentThread()+" - syncFunTwo after : " + NUM); 48 } 49 } 50 51 /** 52 * synchronize修飾的代碼塊,表示該方法中被synchronized修飾的代碼塊是同步的 53 */ 54 public void syncFunThree() { 55 synchronized(LOCK) { 56 Logger.info(Thread.currentThread()+" - syncFunThree before : " + NUM); 57 NUM++; 58 Logger.info(Thread.currentThread()+" - syncFunThree after : " + NUM); 59 } 60 } 61 62 /** 63 * lock.wait()表示等待被lock對象實例的notify()喚醒,才可繼續執行 64 * 注意:使用wait()必須被synchronized修飾 65 * wait()和notify()配對使用,表示在執行上有先后順序 66 */ 67 public void syncFunFour1() { 68 try { 69 while (true) { 70 synchronized (lock) { 71 lock.wait(); //等待被喚醒 72 Logger.info(Thread.currentThread()+" - syncFunFour1 before : " + NUM); 73 NUM++; 74 Logger.info(Thread.currentThread()+" - syncFunFour1 after : " + NUM); 75 } 76 } 77 }catch (InterruptedException e){} 78 } 79 80 /** 81 * lock.notify()表示實例喚醒一個被lock對象wait()的線程 82 * 注意:使用notify()必須被synchronized修飾 83 * wait()和notify()配對使用,表示在執行上有先后順序 84 */ 85 public void syncFunFour2() { 86 try { 87 while (true) { 88 synchronized (lock) { 89 Logger.info(Thread.currentThread()+" - syncFunFour2 before : " + NUM); 90 NUM--; 91 Logger.info(Thread.currentThread()+" - syncFunFour2 after : " + NUM); 92 lock.notify(); //喚醒一個wait的線程 93 } 94 Logger.info(Thread.currentThread()+" - sleep beginning."); 95 Thread.sleep(3000); 96 Logger.info(Thread.currentThread()+" - sleep finished."); 97 } 98 }catch (InterruptedException e){} 99 } 100 101 /** 102 * 測試wait()和notify() 103 * @param test001 104 */ 105 public void testWait(MyThreadTest001 test001){ 106 //執行順序是:對信號量先減1,再喚醒加1線程,每3秒循環執行一次 107 new Thread(() -> test001.syncFunFour1()).start(); //對信號量進行加1操作 108 new Thread(() -> test001.syncFunFour2()).start(); //對信號量進行減1操作 109 } 110 111 112 public static void main(String[] args) { 113 MyThreadTest001 test001 = new MyThreadTest001(); 114 115 //測試synchronized 116 //創建threadCount個線程,對同一信號量進行加1操作,保證信號量同時只被一個線程操作,保證了信號量的一致性 117 int threadCount = 5; 118 while (threadCount-->0) { 119 Thread thread = new Thread(new TestThread(test001)); 120 thread.start(); 121 } 122 123 //測試wait()和notify() 124 // test001.testWait(test001); 125 126 } 127 } 128 129 /** 130 * 創建一個線程 131 */ 132 class TestThread implements Runnable{ 133 private MyThreadTest001 test001; 134 public TestThread(MyThreadTest001 test001) { 135 this.test001 = test001; 136 } 137 public void run() { 138 try { 139 //每個線程每隔50毫秒並循環調用5次 140 for (int i=0;i<5;i++) { 141 test001.syncFunOne(); //此處可以切換為syncFunTwo、syncFunThree進行測試 142 // test001.syncFunTwo(); 143 // test001.syncFunThree(); 144 Thread.sleep(50); 145 } 146 }catch (InterruptedException e) {} 147 } 148 }
測試打印結果:
1 --------------------測試syncFunOne()的打印結果如下-------------------- 2 2018-11-16 23:08:56.047 [INFO] Thread[Thread-0,5,main] - syncFunOne before : 1 3 2018-11-16 23:08:56.048 [INFO] Thread[Thread-0,5,main] - syncFunOne after : 2 4 2018-11-16 23:08:56.049 [INFO] Thread[Thread-4,5,main] - syncFunOne before : 2 5 2018-11-16 23:08:56.049 [INFO] Thread[Thread-4,5,main] - syncFunOne after : 3 6 2018-11-16 23:08:56.049 [INFO] Thread[Thread-3,5,main] - syncFunOne before : 3 7 2018-11-16 23:08:56.049 [INFO] Thread[Thread-3,5,main] - syncFunOne after : 4 8 2018-11-16 23:08:56.049 [INFO] Thread[Thread-2,5,main] - syncFunOne before : 4 9 2018-11-16 23:08:56.049 [INFO] Thread[Thread-2,5,main] - syncFunOne after : 5 10 2018-11-16 23:08:56.049 [INFO] Thread[Thread-1,5,main] - syncFunOne before : 5 11 2018-11-16 23:08:56.049 [INFO] Thread[Thread-1,5,main] - syncFunOne after : 6 12 2018-11-16 23:08:56.100 [INFO] Thread[Thread-2,5,main] - syncFunOne before : 6 13 2018-11-16 23:08:56.100 [INFO] Thread[Thread-2,5,main] - syncFunOne after : 7 14 2018-11-16 23:08:56.100 [INFO] Thread[Thread-0,5,main] - syncFunOne before : 7 15 2018-11-16 23:08:56.100 [INFO] Thread[Thread-0,5,main] - syncFunOne after : 8 16 2018-11-16 23:08:56.100 [INFO] Thread[Thread-3,5,main] - syncFunOne before : 8 17 2018-11-16 23:08:56.100 [INFO] Thread[Thread-3,5,main] - syncFunOne after : 9 18 2018-11-16 23:08:56.100 [INFO] Thread[Thread-4,5,main] - syncFunOne before : 9 19 2018-11-16 23:08:56.100 [INFO] Thread[Thread-4,5,main] - syncFunOne after : 10 20 2018-11-16 23:08:56.101 [INFO] Thread[Thread-1,5,main] - syncFunOne before : 10 21 2018-11-16 23:08:56.101 [INFO] Thread[Thread-1,5,main] - syncFunOne after : 11 22 2018-11-16 23:08:56.151 [INFO] Thread[Thread-3,5,main] - syncFunOne before : 11 23 2018-11-16 23:08:56.151 [INFO] Thread[Thread-3,5,main] - syncFunOne after : 12 24 2018-11-16 23:08:56.151 [INFO] Thread[Thread-2,5,main] - syncFunOne before : 12 25 2018-11-16 23:08:56.151 [INFO] Thread[Thread-2,5,main] - syncFunOne after : 13 26 2018-11-16 23:08:56.151 [INFO] Thread[Thread-0,5,main] - syncFunOne before : 13 27 2018-11-16 23:08:56.151 [INFO] Thread[Thread-0,5,main] - syncFunOne after : 14 28 2018-11-16 23:08:56.152 [INFO] Thread[Thread-4,5,main] - syncFunOne before : 14 29 2018-11-16 23:08:56.152 [INFO] Thread[Thread-4,5,main] - syncFunOne after : 15 30 2018-11-16 23:08:56.152 [INFO] Thread[Thread-1,5,main] - syncFunOne before : 15 31 2018-11-16 23:08:56.152 [INFO] Thread[Thread-1,5,main] - syncFunOne after : 16 32 2018-11-16 23:08:56.202 [INFO] Thread[Thread-0,5,main] - syncFunOne before : 16 33 2018-11-16 23:08:56.202 [INFO] Thread[Thread-0,5,main] - syncFunOne after : 17 34 2018-11-16 23:08:56.202 [INFO] Thread[Thread-2,5,main] - syncFunOne before : 17 35 2018-11-16 23:08:56.202 [INFO] Thread[Thread-2,5,main] - syncFunOne after : 18 36 2018-11-16 23:08:56.202 [INFO] Thread[Thread-3,5,main] - syncFunOne before : 18 37 2018-11-16 23:08:56.202 [INFO] Thread[Thread-3,5,main] - syncFunOne after : 19 38 2018-11-16 23:08:56.203 [INFO] Thread[Thread-4,5,main] - syncFunOne before : 19 39 2018-11-16 23:08:56.203 [INFO] Thread[Thread-4,5,main] - syncFunOne after : 20 40 2018-11-16 23:08:56.203 [INFO] Thread[Thread-1,5,main] - syncFunOne before : 20 41 2018-11-16 23:08:56.203 [INFO] Thread[Thread-1,5,main] - syncFunOne after : 21 42 2018-11-16 23:08:56.253 [INFO] Thread[Thread-0,5,main] - syncFunOne before : 21 43 2018-11-16 23:08:56.253 [INFO] Thread[Thread-0,5,main] - syncFunOne after : 22 44 2018-11-16 23:08:56.253 [INFO] Thread[Thread-2,5,main] - syncFunOne before : 22 45 2018-11-16 23:08:56.253 [INFO] Thread[Thread-2,5,main] - syncFunOne after : 23 46 2018-11-16 23:08:56.253 [INFO] Thread[Thread-3,5,main] - syncFunOne before : 23 47 2018-11-16 23:08:56.253 [INFO] Thread[Thread-3,5,main] - syncFunOne after : 24 48 2018-11-16 23:08:56.254 [INFO] Thread[Thread-4,5,main] - syncFunOne before : 24 49 2018-11-16 23:08:56.254 [INFO] Thread[Thread-4,5,main] - syncFunOne after : 25 50 2018-11-16 23:08:56.254 [INFO] Thread[Thread-1,5,main] - syncFunOne before : 25 51 2018-11-16 23:08:56.254 [INFO] Thread[Thread-1,5,main] - syncFunOne after : 26 52 53 54 --------------------測試syncFunTwo()的打印結果如下-------------------- 55 2018-11-16 23:09:24.966 [INFO] Thread[Thread-0,5,main] - syncFunTwo before : 1 56 2018-11-16 23:09:24.966 [INFO] Thread[Thread-0,5,main] - syncFunTwo after : 2 57 2018-11-16 23:09:24.967 [INFO] Thread[Thread-4,5,main] - syncFunTwo before : 2 58 2018-11-16 23:09:24.967 [INFO] Thread[Thread-4,5,main] - syncFunTwo after : 3 59 2018-11-16 23:09:24.967 [INFO] Thread[Thread-3,5,main] - syncFunTwo before : 3 60 2018-11-16 23:09:24.967 [INFO] Thread[Thread-3,5,main] - syncFunTwo after : 4 61 2018-11-16 23:09:24.967 [INFO] Thread[Thread-2,5,main] - syncFunTwo before : 4 62 2018-11-16 23:09:24.967 [INFO] Thread[Thread-2,5,main] - syncFunTwo after : 5 63 2018-11-16 23:09:24.967 [INFO] Thread[Thread-1,5,main] - syncFunTwo before : 5 64 2018-11-16 23:09:24.967 [INFO] Thread[Thread-1,5,main] - syncFunTwo after : 6 65 2018-11-16 23:09:25.018 [INFO] Thread[Thread-3,5,main] - syncFunTwo before : 6 66 2018-11-16 23:09:25.018 [INFO] Thread[Thread-3,5,main] - syncFunTwo after : 7 67 2018-11-16 23:09:25.018 [INFO] Thread[Thread-1,5,main] - syncFunTwo before : 7 68 2018-11-16 23:09:25.018 [INFO] Thread[Thread-1,5,main] - syncFunTwo after : 8 69 2018-11-16 23:09:25.018 [INFO] Thread[Thread-2,5,main] - syncFunTwo before : 8 70 2018-11-16 23:09:25.018 [INFO] Thread[Thread-2,5,main] - syncFunTwo after : 9 71 2018-11-16 23:09:25.018 [INFO] Thread[Thread-0,5,main] - syncFunTwo before : 9 72 2018-11-16 23:09:25.018 [INFO] Thread[Thread-0,5,main] - syncFunTwo after : 10 73 2018-11-16 23:09:25.019 [INFO] Thread[Thread-4,5,main] - syncFunTwo before : 10 74 2018-11-16 23:09:25.019 [INFO] Thread[Thread-4,5,main] - syncFunTwo after : 11 75 2018-11-16 23:09:25.069 [INFO] Thread[Thread-1,5,main] - syncFunTwo before : 11 76 2018-11-16 23:09:25.069 [INFO] Thread[Thread-1,5,main] - syncFunTwo after : 12 77 2018-11-16 23:09:25.069 [INFO] Thread[Thread-3,5,main] - syncFunTwo before : 12 78 2018-11-16 23:09:25.069 [INFO] Thread[Thread-3,5,main] - syncFunTwo after : 13 79 2018-11-16 23:09:25.069 [INFO] Thread[Thread-2,5,main] - syncFunTwo before : 13 80 2018-11-16 23:09:25.069 [INFO] Thread[Thread-2,5,main] - syncFunTwo after : 14 81 2018-11-16 23:09:25.070 [INFO] Thread[Thread-0,5,main] - syncFunTwo before : 14 82 2018-11-16 23:09:25.070 [INFO] Thread[Thread-0,5,main] - syncFunTwo after : 15 83 2018-11-16 23:09:25.070 [INFO] Thread[Thread-4,5,main] - syncFunTwo before : 15 84 2018-11-16 23:09:25.070 [INFO] Thread[Thread-4,5,main] - syncFunTwo after : 16 85 2018-11-16 23:09:25.120 [INFO] Thread[Thread-1,5,main] - syncFunTwo before : 16 86 2018-11-16 23:09:25.120 [INFO] Thread[Thread-1,5,main] - syncFunTwo after : 17 87 2018-11-16 23:09:25.120 [INFO] Thread[Thread-2,5,main] - syncFunTwo before : 17 88 2018-11-16 23:09:25.120 [INFO] Thread[Thread-2,5,main] - syncFunTwo after : 18 89 2018-11-16 23:09:25.120 [INFO] Thread[Thread-3,5,main] - syncFunTwo before : 18 90 2018-11-16 23:09:25.120 [INFO] Thread[Thread-3,5,main] - syncFunTwo after : 19 91 2018-11-16 23:09:25.121 [INFO] Thread[Thread-4,5,main] - syncFunTwo before : 19 92 2018-11-16 23:09:25.121 [INFO] Thread[Thread-4,5,main] - syncFunTwo after : 20 93 2018-11-16 23:09:25.121 [INFO] Thread[Thread-0,5,main] - syncFunTwo before : 20 94 2018-11-16 23:09:25.121 [INFO] Thread[Thread-0,5,main] - syncFunTwo after : 21 95 2018-11-16 23:09:25.171 [INFO] Thread[Thread-3,5,main] - syncFunTwo before : 21 96 2018-11-16 23:09:25.171 [INFO] Thread[Thread-3,5,main] - syncFunTwo after : 22 97 2018-11-16 23:09:25.171 [INFO] Thread[Thread-1,5,main] - syncFunTwo before : 22 98 2018-11-16 23:09:25.171 [INFO] Thread[Thread-1,5,main] - syncFunTwo after : 23 99 2018-11-16 23:09:25.171 [INFO] Thread[Thread-2,5,main] - syncFunTwo before : 23 100 2018-11-16 23:09:25.171 [INFO] Thread[Thread-2,5,main] - syncFunTwo after : 24 101 2018-11-16 23:09:25.172 [INFO] Thread[Thread-4,5,main] - syncFunTwo before : 24 102 2018-11-16 23:09:25.172 [INFO] Thread[Thread-4,5,main] - syncFunTwo after : 25 103 2018-11-16 23:09:25.172 [INFO] Thread[Thread-0,5,main] - syncFunTwo before : 25 104 2018-11-16 23:09:25.172 [INFO] Thread[Thread-0,5,main] - syncFunTwo after : 26 105 106 --------------------測試syncFunThree()的打印結果如下-------------------- 107 2018-11-16 23:09:43.712 [INFO] Thread[Thread-0,5,main] - syncFunThree before : 1 108 2018-11-16 23:09:43.713 [INFO] Thread[Thread-0,5,main] - syncFunThree after : 2 109 2018-11-16 23:09:43.713 [INFO] Thread[Thread-4,5,main] - syncFunThree before : 2 110 2018-11-16 23:09:43.713 [INFO] Thread[Thread-4,5,main] - syncFunThree after : 3 111 2018-11-16 23:09:43.713 [INFO] Thread[Thread-3,5,main] - syncFunThree before : 3 112 2018-11-16 23:09:43.713 [INFO] Thread[Thread-3,5,main] - syncFunThree after : 4 113 2018-11-16 23:09:43.714 [INFO] Thread[Thread-2,5,main] - syncFunThree before : 4 114 2018-11-16 23:09:43.714 [INFO] Thread[Thread-2,5,main] - syncFunThree after : 5 115 2018-11-16 23:09:43.714 [INFO] Thread[Thread-1,5,main] - syncFunThree before : 5 116 2018-11-16 23:09:43.714 [INFO] Thread[Thread-1,5,main] - syncFunThree after : 6 117 2018-11-16 23:09:43.764 [INFO] Thread[Thread-4,5,main] - syncFunThree before : 6 118 2018-11-16 23:09:43.764 [INFO] Thread[Thread-4,5,main] - syncFunThree after : 7 119 2018-11-16 23:09:43.764 [INFO] Thread[Thread-0,5,main] - syncFunThree before : 7 120 2018-11-16 23:09:43.764 [INFO] Thread[Thread-0,5,main] - syncFunThree after : 8 121 2018-11-16 23:09:43.765 [INFO] Thread[Thread-1,5,main] - syncFunThree before : 8 122 2018-11-16 23:09:43.765 [INFO] Thread[Thread-1,5,main] - syncFunThree after : 9 123 2018-11-16 23:09:43.765 [INFO] Thread[Thread-2,5,main] - syncFunThree before : 9 124 2018-11-16 23:09:43.765 [INFO] Thread[Thread-2,5,main] - syncFunThree after : 10 125 2018-11-16 23:09:43.765 [INFO] Thread[Thread-3,5,main] - syncFunThree before : 10 126 2018-11-16 23:09:43.765 [INFO] Thread[Thread-3,5,main] - syncFunThree after : 11 127 2018-11-16 23:09:43.814 [INFO] Thread[Thread-4,5,main] - syncFunThree before : 11 128 2018-11-16 23:09:43.814 [INFO] Thread[Thread-4,5,main] - syncFunThree after : 12 129 2018-11-16 23:09:43.814 [INFO] Thread[Thread-0,5,main] - syncFunThree before : 12 130 2018-11-16 23:09:43.814 [INFO] Thread[Thread-0,5,main] - syncFunThree after : 13 131 2018-11-16 23:09:43.815 [INFO] Thread[Thread-1,5,main] - syncFunThree before : 13 132 2018-11-16 23:09:43.815 [INFO] Thread[Thread-1,5,main] - syncFunThree after : 14 133 2018-11-16 23:09:43.815 [INFO] Thread[Thread-3,5,main] - syncFunThree before : 14 134 2018-11-16 23:09:43.815 [INFO] Thread[Thread-3,5,main] - syncFunThree after : 15 135 2018-11-16 23:09:43.815 [INFO] Thread[Thread-2,5,main] - syncFunThree before : 15 136 2018-11-16 23:09:43.815 [INFO] Thread[Thread-2,5,main] - syncFunThree after : 16 137 2018-11-16 23:09:43.865 [INFO] Thread[Thread-4,5,main] - syncFunThree before : 16 138 2018-11-16 23:09:43.865 [INFO] Thread[Thread-4,5,main] - syncFunThree after : 17 139 2018-11-16 23:09:43.865 [INFO] Thread[Thread-0,5,main] - syncFunThree before : 17 140 2018-11-16 23:09:43.865 [INFO] Thread[Thread-0,5,main] - syncFunThree after : 18 141 2018-11-16 23:09:43.866 [INFO] Thread[Thread-2,5,main] - syncFunThree before : 18 142 2018-11-16 23:09:43.866 [INFO] Thread[Thread-2,5,main] - syncFunThree after : 19 143 2018-11-16 23:09:43.866 [INFO] Thread[Thread-1,5,main] - syncFunThree before : 19 144 2018-11-16 23:09:43.866 [INFO] Thread[Thread-1,5,main] - syncFunThree after : 20 145 2018-11-16 23:09:43.866 [INFO] Thread[Thread-3,5,main] - syncFunThree before : 20 146 2018-11-16 23:09:43.866 [INFO] Thread[Thread-3,5,main] - syncFunThree after : 21 147 2018-11-16 23:09:43.916 [INFO] Thread[Thread-0,5,main] - syncFunThree before : 21 148 2018-11-16 23:09:43.916 [INFO] Thread[Thread-0,5,main] - syncFunThree after : 22 149 2018-11-16 23:09:43.916 [INFO] Thread[Thread-4,5,main] - syncFunThree before : 22 150 2018-11-16 23:09:43.916 [INFO] Thread[Thread-4,5,main] - syncFunThree after : 23 151 2018-11-16 23:09:43.917 [INFO] Thread[Thread-1,5,main] - syncFunThree before : 23 152 2018-11-16 23:09:43.917 [INFO] Thread[Thread-1,5,main] - syncFunThree after : 24 153 2018-11-16 23:09:43.917 [INFO] Thread[Thread-3,5,main] - syncFunThree before : 24 154 2018-11-16 23:09:43.917 [INFO] Thread[Thread-3,5,main] - syncFunThree after : 25 155 2018-11-16 23:09:43.917 [INFO] Thread[Thread-2,5,main] - syncFunThree before : 25 156 2018-11-16 23:09:43.917 [INFO] Thread[Thread-2,5,main] - syncFunThree after : 26 157 158 --------------------測試測試wait()和notify()的打印結果如下-------------------- 159 2018-11-16 23:10:09.376 [INFO] Thread[Thread-1,5,main] - syncFunFour2 before : 1 160 2018-11-16 23:10:09.380 [INFO] Thread[Thread-1,5,main] - syncFunFour2 after : 0 161 2018-11-16 23:10:09.380 [INFO] Thread[Thread-1,5,main] - sleep beginning. 162 2018-11-16 23:10:09.380 [INFO] Thread[Thread-0,5,main] - syncFunFour1 before : 0 163 2018-11-16 23:10:09.380 [INFO] Thread[Thread-0,5,main] - syncFunFour1 after : 1 164 2018-11-16 23:10:12.381 [INFO] Thread[Thread-1,5,main] - sleep finished. 165 2018-11-16 23:10:12.381 [INFO] Thread[Thread-1,5,main] - syncFunFour2 before : 1 166 2018-11-16 23:10:12.381 [INFO] Thread[Thread-1,5,main] - syncFunFour2 after : 0 167 2018-11-16 23:10:12.381 [INFO] Thread[Thread-1,5,main] - sleep beginning. 168 2018-11-16 23:10:12.381 [INFO] Thread[Thread-0,5,main] - syncFunFour1 before : 0 169 2018-11-16 23:10:12.381 [INFO] Thread[Thread-0,5,main] - syncFunFour1 after : 1 170 2018-11-16 23:10:15.382 [INFO] Thread[Thread-1,5,main] - sleep finished. 171 2018-11-16 23:10:15.382 [INFO] Thread[Thread-1,5,main] - syncFunFour2 before : 1 172 2018-11-16 23:10:15.382 [INFO] Thread[Thread-1,5,main] - syncFunFour2 after : 0 173 2018-11-16 23:10:15.382 [INFO] Thread[Thread-1,5,main] - sleep beginning. 174 2018-11-16 23:10:15.382 [INFO] Thread[Thread-0,5,main] - syncFunFour1 before : 0 175 2018-11-16 23:10:15.382 [INFO] Thread[Thread-0,5,main] - syncFunFour1 after : 1 176 2018-11-16 23:10:18.382 [INFO] Thread[Thread-1,5,main] - sleep finished. 177 2018-11-16 23:10:18.382 [INFO] Thread[Thread-1,5,main] - syncFunFour2 before : 1 178 2018-11-16 23:10:18.382 [INFO] Thread[Thread-1,5,main] - syncFunFour2 after : 0 179 2018-11-16 23:10:18.382 [INFO] Thread[Thread-1,5,main] - sleep beginning. 180 2018-11-16 23:10:18.382 [INFO] Thread[Thread-0,5,main] - syncFunFour1 before : 0 181 2018-11-16 23:10:18.382 [INFO] Thread[Thread-0,5,main] - syncFunFour1 after : 1 182 2018-11-16 23:10:21.383 [INFO] Thread[Thread-1,5,main] - sleep finished. 183 2018-11-16 23:10:21.383 [INFO] Thread[Thread-1,5,main] - syncFunFour2 before : 1 184 2018-11-16 23:10:21.383 [INFO] Thread[Thread-1,5,main] - syncFunFour2 after : 0 185 2018-11-16 23:10:21.383 [INFO] Thread[Thread-1,5,main] - sleep beginning. 186 2018-11-16 23:10:21.383 [INFO] Thread[Thread-0,5,main] - syncFunFour1 before : 0 187 2018-11-16 23:10:21.383 [INFO] Thread[Thread-0,5,main] - syncFunFour1 after : 1 188 此處省略...
二、 ReentrantLock(可重入鎖)和 ReentrantReadWriteLock(讀寫鎖)的用法
ReentrantLock 是一個樂觀鎖,實現的時候需要手動加鎖和釋放鎖,例如:
1 import java.util.Random; 2 import java.util.concurrent.*; 3 4 public class MyTest { 5 6 int num = 1; //對num進行逐1累加 7 final ReentrantLock lock = new ReentrantLock(); 8 9 final class MyWork implements Runnable { 10 public void run() { 11 while (true) { 12 Thread.sleep(new Random().nextInt(2000)+300); 13 try { 14 lock.lock(); 15 System.out.println(Thread.currentThread().getName()+" : "+ ++num); 16 } finally { 17 lock.unlock(); 18 } 19 } 20 } 21 } 22 23 public void execute() { 24 ExecutorService executorService = Executors.newFixedThreadPool(5); 25 executorService.submit(new MyWork()); 26 executorService.submit(new MyWork()); 27 executorService.submit(new MyWork()); 28 } 29 }

三、常用的java同步組件
//計數類
java.util.concurrent.CountDownLatch
可用於多線程並發等場景。
構造器:CountDownLatch(int count)
主要方法有:await()、getCount()、countDown()
實現思想是通過unsafe.xxx (Unsafe unsafe = Unsafe.getUnsafe())
//原子類
java.util.concurrent.atomic.AtomicInteger
封裝了原子操作:讀寫數據。
主要構造器有:AtomicInteger(int initialValue)、AtomicInteger()
主要方法有:get()、set(int newValue)、getAndSet(int newValue)、compareAndSet(int expect, int update)、getAndIncrement()、getAndDecrement()
實現思想是通過unsafe.xxx (Unsafe unsafe = Unsafe.getUnsafe())
其他原子類如:AtomicBoolean、AtomicIntegerArray、AtomicLong、AtomicReference<V>等
