生产者,消费者模式
- synchronized
- lock condition对象等待唤醒
- 线程定制化调用通信
一个线程生产,一个线程消费。
两种实现方式:
- synchronized关键字
- 灵活的lock锁
一个线程新增1,一个消费0,按顺序进行。保证最后的数据为0;
synchronized
/*等待 唤醒 (生产 通知)* 1. 高内聚的情况下 多线程操作同一个资源* 2. 判断 干活 通知* 3. 防止虚假唤醒 (while 替代if解决)** @author echo lovely* @date 2021/2/17 11:12*//*** thread demo by synchronized keywords*/
class AirCondition {// wait || awaitprivate int num = 0;synchronized void increment() throws InterruptedException {while (num != 0) {// 等待 不生产this.wait();}num++;System.out.println(Thread.currentThread().getName() + "\t" + num);// 唤醒其它线程消费this.notifyAll();}synchronized void decrease() throws InterruptedException {while (num == 0) {// 没有东西 需要等待 不能消费this.wait();}this.num--;System.out.println(Thread.currentThread().getName() + "\t" + num);// 唤醒生产者生产this.notifyAll();}}
private static void waitNotify() {AirCondition ac = new AirCondition();new Thread(() -> {for (int i = 0; i < 10; i++) {try {ac.increment();} catch (InterruptedException e) {e.printStackTrace();}}}, "A").start();new Thread(() -> {for (int i = 0; i < 10; i++) {try {ac.decrease();} catch (InterruptedException e) {e.printStackTrace();}}}, "B").start();new Thread(() -> {for (int i = 0; i < 10; i++) {try {ac.increment();} catch (InterruptedException e) {e.printStackTrace();}}}, "C").start();new Thread(() -> {for (int i = 0; i < 10; i++) {try {ac.decrease();} catch (InterruptedException e) {e.printStackTrace();}}}, "D").start();
}
lock condition对象等待唤醒
/*** thread demo by lock*/
class AirCondition1 {// lock -> product or consumerprivate int num = 0;// 非公平锁private final Lock lock = new ReentrantLock();// 用于lock的等待和唤醒 monitorprivate final Condition condition = lock.newCondition();void increment() {lock.lock();try {while (num != 0) {condition.await();}num++;System.out.println(Thread.currentThread().getName() + "\t" + num);condition.signalAll();} catch (Exception e) {e.printStackTrace();} finally {lock.unlock();}}void decrease() {lock.lock();try {while (num == 0) {// 没有可消费 等待condition.await();}num--;System.out.println(Thread.currentThread().getName() + "\t" + num);// 唤醒生产者生产condition.signalAll();} catch (Exception e) {e.printStackTrace();} finally {lock.unlock();}}}
private static void awaitSignal() {AirCondition1 condition = new AirCondition1();// thread one productnew Thread(() -> {for (int i = 0; i < 10; i++) {condition.increment();}}, "Rye").start();// thread two consumernew Thread(() -> {for (int i = 0; i < 10; i++) {condition.decrease();}}, "sevenYoungAiRye").start();// thread three productnew Thread(() -> {for (int i = 0; i < 10; i++) {condition.increment();}}, "hh1").start();// thread four consumernew Thread(() -> {for (int i = 0; i < 10; i++) {condition.decrease();}}, "hh2").start();}
线程定制化调用通信
A 线程do sth…
B 线程do sth…
C线程do sthh…
如何保证上面轮询干事?
使用Condtion对象, 拿到对象的锁。
package top.bitqian.demo1;import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;/*** 题目:* 三个线程之间 打印 5 10 15 次。轮询打印10次。* @author echo lovely* @date 2021/2/17 18:43*/class ShareData {private int num = 1; // 1 A, 2 B, 3 Cprivate final Lock lock = new ReentrantLock();// 三把钥匙 用于解锁Condition c1 = lock.newCondition();Condition c2 = lock.newCondition();Condition c3 = lock.newCondition();void print5() {try {lock.lock();// 1. 判断while (num != 1) {// 等待c1.await();}// 2. 干活for (int i = 0; i < 5; i++) {System.out.println(Thread.currentThread().getName() + "\t" + i);}// 3. 通知num = 2;// 唤醒第二个线程c2.signal();} catch (Exception e) {e.printStackTrace();} finally {lock.unlock();}}void print10() {try {lock.lock();// 线程2 等待while (num != 2) {c2.await();}for (int i = 0; i < 10; i++) {System.out.println(Thread.currentThread().getName() + "\t" + i);}// 通知三个线程num = 3;c3.signal();} catch (Exception e) {e.printStackTrace();} finally {lock.unlock();}}void print15() {try {lock.lock();while (num != 3) {c3.await();}for (int i = 0; i < 15; i++) {System.out.println(Thread.currentThread().getName() + "\t" + i);}// 通知线程1num = 1;c1.signal();} catch (Exception e) {e.printStackTrace();} finally {lock.unlock();}}}public class ConditionDemo {public static void main(String[] args) {ShareData shareData = new ShareData();new Thread(() -> {for (int i = 0; i < 10; i++) {shareData.print5();}}, "A").start();new Thread(() -> {for (int i = 0; i < 10; i++) {shareData.print10();}}, "B").start();new Thread(() -> {for (int i = 0; i < 10; i++) {shareData.print15();}}, "C").start();}}