生産者和消費者
線程直接的通信,線程之間要協調和排程
生産者和消費者synchronized版
/**
* 題目:現在兩個線程,可以操作初始值為0的一個變量實作一個線程對該變量+1,
* 一個線程對該變量-1,實作交替10次
*/
public class B {
public static void main(String[] args) {
Data data = new Data();
new Thread(() -> {
for (int i = 1; i <= 10; i++) {
try {
data.increment();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, "A").start();
new Thread(() -> {
for (int i = 1; i <= 10; i++) {
try {
data.decrement();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, "B").start();
}
}
class Data{
private int number = 0;
public synchronized void increment() throws InterruptedException {
while (number != 0) {
this.wait();
}
number++;
System.out.println(Thread.currentThread().getName() + "\t" + number);
this.notifyAll();
}
public synchronized void decrement() throws InterruptedException {
while (number == 0) {
this.wait();
}
number--;
System.out.println(Thread.currentThread().getName() + "\t" + number);
this.notifyAll();
}
}
**【注意】**包裹this.wait()方法的是while循環,因為如果相同功能的線程不隻一個的時候(多個加線程或者多個減線程)notifyAll喚醒多個等待的線程,但是隻能有一個并運作獲得,使用while可以實時判斷目前該線程被喚醒時候是否符合條件。
新版生産者和消費者的寫法
Condition用作對象螢幕。lock替換sychronized,Condition取代對象螢幕方法的使用。
public class C {
public static void main(String[] args) {
Data2 data = new Data2();
new Thread(() -> {
for (int i = 1; i <= 10; i++) {
data.increment();
}
},"A").start();
new Thread(() -> {
for (int i = 1; i <= 10; i++) {
data.decrement();
}
},"B").start();
}
}
class Data2{
private int number = 0;
private Lock lock = new ReentrantLock();
private Condition condition = lock.newCondition();
public void increment(){
lock.lock();
try {
while (number != 0) {
condition.await();
}
number++;
System.out.println(Thread.currentThread().getName() + "\t" + number);
condition.signalAll();
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
lock.unlock();
}
}
public void decrement(){
lock.lock();
try {
while (number == 0) {
condition.await();
}
number--;
System.out.println(Thread.currentThread().getName() + "\t" + number);
condition.signalAll();
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
lock.unlock();
}
}
}
精确通知順序通路
定義多個Condition實作多線程順序通路
public class D {
public static void main(String[] args) {
Resources resources = new Resources();
new Thread(() -> {
for (int i = 1; i <= 10; i++) {
resources.printA();
}
}, "AA").start();
new Thread(() -> {
for (int i = 1; i <= 10; i++) {
resources.printB();
}
}, "BB").start();
new Thread(() -> {
for (int i = 1; i <= 10; i++) {
resources.printC();
}
}, "CC").start();
}
}
class Resources{
private int number = 1; //1A 2B 3C
private 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();
}
System.out.println(Thread.currentThread().getName() + '\t');
number = 2;
condition2.signal();
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public void printB() {
lock.lock();
try {
while (number != 2) {
condition2.await();
}
System.out.println(Thread.currentThread().getName() + '\t');
number = 3;
condition3.signal();
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public void printC() {
lock.lock();
try {
while (number != 3) {
condition3.await();
}
System.out.println(Thread.currentThread().getName() + '\t');
number = 1;
condition1.signal();
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}