生产者和消费者
线程直接的通信,线程之间要协调和调度
生产者和消费者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();
}
}
}