Table of Contents
ToggleDifference Between Condition signal and signalAll in Java
使用條件等待和信號,也就是取得一個 lock 鎖後,調用 await 方法,進入等待的所有執行緒,有兩種方法可以通知等待執行緒,一個是 signal 隨機喚醒一個正在等待該對象鎖的執行緒,另一個是 signalAll 喚醒所有正在等待該對象鎖的執行緒, Condition signal and signalAll Methods in Java 這表示一旦讓該執行緒暫停執行並且釋放鎖,其他執行緒就可以取得該鎖,喚醒該執行緒,繼續執行符合條件的任務,本篇增加了範例,並透過單元測試來驗證產出結果。
檔案目錄
./
+- src
+- test
| +- org
| +- ruoxue
| +- java_147
| +- synchronization
| +- reentrantlock
| +- DifferenceConditionSignalSignalAllTest.java
單元測試
Java Condition signal signalAll Methods 提供執行緒條件暫停、條件喚醒等操作。
signal
Java Condition signal signalAll Methods 建立 1 個物件做為鎖,建立 3 條執行緒,先取得 lock 後,調用 await 暫停當前的執行緒,然後由主執行緒調用 signal ,隨機喚醒一個正在等待該對象鎖的執行緒。
@Test
public void signal() {
Lock lock = new ReentrantLock();
Condition condition = lock.newCondition();
List<Thread> threads = Stream.generate(() -> new Thread(() -> {
try {
lock.lock();
try {
System.out.println(String.format("T[%d] waiting", Thread.currentThread().getId()));
condition.await();
System.out.println(String.format("T[%d] finished", Thread.currentThread().getId()));
} finally {
lock.unlock();
}
} catch (InterruptedException ex) {
ex.printStackTrace();
}
})).limit(3).collect(Collectors.toList());
threads.forEach(e -> e.start());
try {
TimeUnit.SECONDS.sleep(3);
lock.lock();
try {
System.out.println(String.format("T[%d] signal", Thread.currentThread().getId()));
condition.signal();
System.out.println(String.format("T[%d] finished", Thread.currentThread().getId()));
} finally {
lock.unlock();
}
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
T[11] waiting
T[12] waiting
T[13] waiting
T[1] signal
T[1] finished
T[11] finished
signalAll
Java Condition signal signalAll Methods 建立 1 個物件做為鎖,建立 3 條執行緒,先取得 lock 後,調用 await 暫停當前的執行緒,然後由主執行緒調用 signalAll ,喚醒所有正在等待該對象鎖的執行緒,重新參與競爭。
@Test
public void signalAll() {
Lock lock = new ReentrantLock();
Condition condition = lock.newCondition();
List<Thread> threads = Stream.generate(() -> new Thread(() -> {
try {
lock.lock();
try {
System.out.println(String.format("T[%d] waiting", Thread.currentThread().getId()));
condition.await();
System.out.println(String.format("T[%d] finished", Thread.currentThread().getId()));
} finally {
lock.unlock();
}
} catch (InterruptedException ex) {
ex.printStackTrace();
}
})).limit(3).collect(Collectors.toList());
threads.forEach(e -> e.start());
try {
TimeUnit.SECONDS.sleep(3);
lock.lock();
try {
System.out.println(String.format("T[%d] signalAll", Thread.currentThread().getId()));
condition.signalAll();
System.out.println(String.format("T[%d] finished", Thread.currentThread().getId()));
} finally {
lock.unlock();
}
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
T[11] waiting
T[12] waiting
T[13] waiting
T[1] signalAll
T[1] finished
T[11] finished
T[12] finished
T[13] finished
DifferenceConditionSignalSignalAllTest.java
Condition signal signalAll Java 新增單元測試,驗證 Condition signal and signalAll Methods in Java 是否符合預期。
package org.ruoxue.java_147.synchronization.reentrantlock;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.junit.Test;
public class DifferenceConditionSignalSignalAllTest {
@Test
public void signal() {
Lock lock = new ReentrantLock();
Condition condition = lock.newCondition();
List<Thread> threads = Stream.generate(() -> new Thread(() -> {
try {
lock.lock();
try {
System.out.println(String.format("T[%d] waiting", Thread.currentThread().getId()));
condition.await();
System.out.println(String.format("T[%d] finished", Thread.currentThread().getId()));
} finally {
lock.unlock();
}
} catch (InterruptedException ex) {
ex.printStackTrace();
}
})).limit(3).collect(Collectors.toList());
threads.forEach(e -> e.start());
try {
TimeUnit.SECONDS.sleep(3);
lock.lock();
try {
System.out.println(String.format("T[%d] signal", Thread.currentThread().getId()));
condition.signal();
System.out.println(String.format("T[%d] finished", Thread.currentThread().getId()));
} finally {
lock.unlock();
}
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
@Test
public void signalAll() {
Lock lock = new ReentrantLock();
Condition condition = lock.newCondition();
List<Thread> threads = Stream.generate(() -> new Thread(() -> {
try {
lock.lock();
try {
System.out.println(String.format("T[%d] waiting", Thread.currentThread().getId()));
condition.await();
System.out.println(String.format("T[%d] finished", Thread.currentThread().getId()));
} finally {
lock.unlock();
}
} catch (InterruptedException ex) {
ex.printStackTrace();
}
})).limit(3).collect(Collectors.toList());
threads.forEach(e -> e.start());
try {
TimeUnit.SECONDS.sleep(3);
lock.lock();
try {
System.out.println(String.format("T[%d] signalAll", Thread.currentThread().getId()));
condition.signalAll();
System.out.println(String.format("T[%d] finished", Thread.currentThread().getId()));
} finally {
lock.unlock();
}
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
}
心得分享
Java Condition signal signalAll with Examples 在互斥鎖的情況下,執行緒可能會取得獨占鎖,當發現不具備繼續執行的所需條件時,該執行緒會釋放鎖,並將其狀態改變為等待狀態,直到滿足必要的條件為止,這表示另一條執行緒,稍後將會向當前等待的執行緒發出信號,調用 signal 或 signalAll 方法,以通知其他等待的單一或多個執行緒,重新取得鎖,並檢查是否已經滿足執行的必要條件, Condition signal signalAll Java 提供這兩個方法的應用與場景。