一、传统版
代码案例:
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
class ShareData // 资源类
{
private int number = 0;
private Lock lock = new ReentrantLock();
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();
}
}
}
/**
* 一个初始值为0的变量,两个线程对其进行交替操作,一个加1一个减1,来5轮
*
* 1 线程 操作 资源类
* 2 判断 干活 通知
* 3 防止虚假唤醒机制
*/
public class ProdConsumer_TraditionDemo {
public static void main(String[] args) {
ShareData shareData = new ShareData();
new Thread(()->{
for (int i = 1; i <= 5; i++){
try {
shareData.increment();
} catch (Exception e) {
e.printStackTrace();
}
}
},"AAA").start();
new Thread(()->{
for (int i = 1; i <= 5; i++){
try {
shareData.decrement();
} catch (Exception e) {
e.printStackTrace();
}
}
},"BBB").start();
}
}
AAA 1
BBB 0
AAA 1
BBB 0
AAA 1
BBB 0
AAA 1
BBB 0
AAA 1
BBB 0
多线程的判断必须使用while,不能使用if。
二、阻塞队列版
代码案例:
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
class MyResource{
private volatile boolean FLAG = true; // 默认开启,进行生产+消费
private AtomicInteger atomicInteger = new AtomicInteger();
BlockingQueue<String> blockingQueue = null;
public MyResource(BlockingQueue<String> blockingQueue){
this.blockingQueue = blockingQueue;
System.out.println(blockingQueue.getClass().getName());
}
public void myProd()throws Exception{
String data = null;
boolean retValue;
while(FLAG){
data = atomicInteger.incrementAndGet()+"";
retValue = blockingQueue.offer(data, 2L, TimeUnit.SECONDS);
if(retValue){
System.out.println(Thread.currentThread().getName()+"\t 插入队列" + data + "成功");
}else{
System.out.println(Thread.currentThread().getName()+"\t 插入队列" + data + "失败");
}
TimeUnit.SECONDS.sleep(1);
}
System.out.println(Thread.currentThread().getName()+"\t大老板叫停了,表示FLAG=false,生产动作结束");
}
public void myConsumer()throws Exception{
String result = null;
boolean retValue;
while(FLAG){
result = blockingQueue.poll(2L, TimeUnit.SECONDS);
if(null == result || result.equals("")){
FLAG = false;
System.out.println(Thread.currentThread().getName()+"\t 超过2秒钟没有取到蛋糕,消费退出");
System.out.println();
System.out.println();
return ;
}
System.out.println(Thread.currentThread().getName()+"\t 消费队列" + result + "成功");
}
}
public void stop()throws Exception{
this.FLAG = false;
}
}
/**
* volatile/CAS/atomicInteger/BlockQueue/线程交互/原子引用
*/
public class ProdConsumer_BlockQueueDemo {
public static void main(String[] args) throws Exception{
MyResource myResource = new MyResource(new ArrayBlockingQueue<>(10));
new Thread(()->{
System.out.println(Thread.currentThread().getName()+"\t 生产线程启动");
try{
myResource.myProd();
}catch (Exception e){
e.printStackTrace();
}
},"Prod").start();
new Thread(()->{
System.out.println(Thread.currentThread().getName()+"\t 消费线程启动");
try{
myResource.myConsumer();
System.out.println();
System.out.println();
}catch (Exception e){
e.printStackTrace();
}
},"Consumer").start();
// 暂停一会儿线程
try { TimeUnit.SECONDS.sleep(5); } catch (InterruptedException e) { e.printStackTrace(); }
System.out.println();
System.out.println();
System.out.println();
System.out.println("5秒钟时间到,大老板main线程叫停,活动结束");
myResource.stop();
}
}
java.util.concurrent.ArrayBlockingQueue
Prod 生产线程启动
Prod 插入队列1成功
Consumer 消费线程启动
Consumer 消费队列1成功
Prod 插入队列2成功
Consumer 消费队列2成功
Prod 插入队列3成功
Consumer 消费队列3成功
Prod 插入队列4成功
Consumer 消费队列4成功
Prod 插入队列5成功
Consumer 消费队列5成功
5秒钟时间到,大老板main线程叫停,活动结束
Prod 大老板叫停了,表示FLAG=false,生产动作结束
Consumer 超过2秒钟没有取到蛋糕,消费退出