生产者消费者
举例:现在两个线程,可以操作初始值为零的一个变量,实现一个线程对该变量+1,一个线程对该变量-1,实现交替,来10轮,变量初始值最终为零,下面每句都很干
package com.magic.juc0117;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* @Description
* @Author Chelsea
* @Date 2020/1/18 0:10
*/
class Aircondition{
private int number =0;
Lock lock = new ReentrantLock();
//Lock support Condition
//Lock replace synchronized ,Condition replace monitor 官方文档
//也就是当Lock取代synchronized时,Condition会替代monitor机制!!
private Condition condition = lock.newCondition();
public void increment() throws Exception{
lock.lock();
try{
//1.判断
while (number != 0){
condition.await();
}
//2.干活
number++;
System.out.println(Thread.currentThread().getName()+"\t"+number);
//3.通知
condition.signalAll();
} catch (Exception e){
e.printStackTrace();
} finally {
lock.unlock();
}
}
public void decrement () throws Exception{
lock.lock();
try{
//1.判断
while (number == 0){
condition.await();
}
//2.干活
number--;
System.out.println(Thread.currentThread().getName()+"\t"+number);
//3.通知
condition.signalAll();
} catch (Exception e){
e.printStackTrace();
} finally {
lock.unlock();
}
}
// 注释掉的是以synchronized举例 wait、notify 和 synchronized一起用
// public synchronized void increment() throws Exception{
// //1.判断
// while (number != 0){
// this.wait();
// }
// //2.干活
// number++;
// System.out.println(Thread.currentThread().getName()+"\t"+number);
// //3.通知
// this.notifyAll();
// }
//
// public synchronized void decrement () throws Exception{
// //1.判断
// while (number == 0){
// this.wait();
// }
// number--;
// System.out.println(Thread.currentThread().getName()+"\t"+number);
// this.notifyAll();
// }
}
/**
* 重点!!
* 1.高内聚低耦合前提下,线程操作资源类
* 2.判断/干活/通知
* 3.防止虚假唤醒 多线程的交互判断绝对不可以用if 要用while 官方文档Object.wait()方法
* 重点 判断 wait while循环加判断
*/
public class ProducerConsumerDemo04 {
public static void main(String[] args) {
Aircondition aircondition = new Aircondition();
new Thread(() -> {
for (int i = 0; i < 10 ; i++) {
try {
aircondition.increment();
} catch (Exception e) {
e.printStackTrace();
}
}
},"A").start();
new Thread(new Runnable() {
public void run() {
for (int i = 0; i < 10; i++) {
try {
aircondition.decrement();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}, "B").start();
new Thread(new Runnable() {
public void run() {
for (int i = 0; i < 10; i++) {
try {
aircondition.increment();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}, "C").start();
new Thread(new Runnable() {
public void run() {
for (int i = 0; i < 10; i++) {
try {
aircondition.decrement();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}, "D").start();
}
//判断如果用if 则2个线程一切正常,为什么4个线程用if会等于2? 用if不会再拉回判断可能同时唤醒两个+线程,就可能出现为2的情况,所以必须用while,if 仅仅是判断,while是循环加判断,用while可以防止虚假唤醒
}
Condition
lock可以实现精准控制,Condition大显身手:
package com.magic.juc0117;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
class ShareData{ //低耦合高内聚封装
private int number = 1;//A1 B2 C3
private Lock lock = new ReentrantLock();
//相当于一把锁配多把备用钥匙
private Condition condition1 = lock.newCondition();
private Condition condition2 = lock.newCondition();
private Condition condition3 = lock.newCondition();
public void print5(){
lock.lock();
try{
//1.判断
while (number !=1){
//wait
condition1.await();
}
//2.干活
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName()+"--"+i);
}
//3.通知
number = 2;
//如何通知线程2
condition2.signal();
} catch (Exception e){
e.printStackTrace();
} finally {
lock.unlock();
}
}
public void print10(){
lock.lock();
try{
//1.判断
while (number !=2){
//wait
condition2.await();
}
//2.干活
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName()+"--"+i);
}
//3.通知
number = 3;
//如何通知线程2
condition3.signal();
} catch (Exception e){
e.printStackTrace();
} finally {
lock.unlock();
}
}
public void print15(){
lock.lock();
try{
//1.判断
while (number !=3){
//wait
condition3.await();
}
//2.干活
for (int i = 0; i < 15; i++) {
System.out.println(Thread.currentThread().getName()+"--"+i);
}
//3.通知
number = 1;
//如何通知线程2
condition1.signal();
} catch (Exception e){
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
/**
* lock可以实现精准控制
* 备注:多线程之间精准调用,实现A》B》C
* 三个线程启动,要求如下
*
* AA打印5次,BB打印10次,CC打印15次
* 接着
* AA打印5次,BB打印10次,CC打印15次
* 来10轮
*/
public class ConditionDemo {
public static void main(String[] args) {
ShareData shareData = new ShareData();
new Thread(() -> {
for (int i = 0; i < 10; i++) {
shareData.print5();
}
},"AA").start();
new Thread(() -> {
for (int i = 0; i < 10; i++) {
shareData.print10();
}
},"BB").start();
new Thread(() -> {
for (int i = 0; i < 15; i++) {
shareData.print15();
}
},"CC").start();
}
}
学习整理于JUC.