Lock版的生産者消費者問題
那麼在synchronized中呢,我們是使用wait和notify來控制線程的。
public synchronized void increment() throws InterruptedException {
while (number != 0) {
// 等待
this.wait();100);
number++; // 業務
System.out.println(Thread.currentThread().getName() + " => " + number);
// 通知其它線程我+1加完了
this.notifyAll();
用了Lock之後、會有一些細微的改變,wait->condition.await, notify->condition.signal
class doSomething {
private int number = 0;
Lock lock = new ReentrantLock();
Condition condition = lock.newCondition();
// +1
public void increse() throws InterruptedException {
lock.lock();
try {
while (number != 0) {
condition.await();100);
number++;
System.out.println(Thread.currentThread().getName() + "->" +condition.signalAll();catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
// -1
public void decrese() throws InterruptedException {
lock.lock();
try {
while (number == 0) {
condition.await();100);
number--;
System.out.println(Thread.currentThread().getName() + "->" + number);
condition.signalAll();
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
思考:既然有了wait和notify、那為什麼我們還要多此一舉來使用condition的等待和喚醒呢?
這是因為condition能夠做到有序,精準的通知和喚醒線程
那麼如何做到有序精準的來喚醒線程呢?
public class C {
public static void main(String[] args) {
doSomething2 doSomething2 = new doSomething2();
new Thread(() -> {
for (int i = 0; i < 10; i++) {
doSomething2.printA();
}
}, "A").start();
new Thread(() -> {
for (int i = 0; i < 10; i++) {
doSomething2.printB();
}
}, "B").start();
new Thread(() -> {
for (int i = 0; i < 10; i++) {
doSomething2.printC();
}
}, "C").start();
}
}
@SuppressWarnings("all")
class doSomething2 {
private int number = 1;
Lock lock = new ReentrantLock();
private Condition condition1 = lock.newCondition();
private Condition condition2 = lock.newCondition();
private Condition condition3 = lock.newCondition();
public void printA() {
lock.lock();
try {
while (number != 1) {
// 等待
condition1.await();
}
Thread.sleep(100);
System.out.println(Thread.currentThread().getName() + "AAA");
// 喚醒
condition2.signal();catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public void printB() {
lock.lock();
try {
while (number != 1) {
// 等待
condition2.await();
}
Thread.sleep(100);
System.out.println(Thread.currentThread().getName() + "BBB");
// 喚醒
condition3.signal();catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public void printC() {
lock.lock();
try {
while (number != 1) {
// 等待
condition3.await();
}
Thread.sleep(100);
System.out.println(Thread.currentThread().getName() + "CCC");
// 喚醒
condition1.signal();catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}