一、阻塞队列
阻塞队列,顾名思义。首先他是一个队列,而一个阻塞队列在数据结构中所起的作用大致如下图所示
当阻塞队列是 空 的时候,从队列中 获取 元素的操作将会被阻塞。
当阻塞队列是 满 的时候,从队列中 添加 元素的操作将会被阻塞。
BlockingQueue
下面来看一张图
七个是实现类:
方法:
SynchronousQueue
阻塞列队使用场景模拟
传统生产者和消费者的线程通信 的代码:
/*
* Copyright (C), 2013-2019, 天津大海云科技有限公司
*/
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* 生产消费模式
* 两个线程,一个生产面包,一个消费面包
*
* @author yangjikang
* @date 2019/6/17 17:33
* @modified By yangjikang
*/
class ShareData {
private int number = 0;
private Lock lock = new ReentrantLock();
private Condition condition = lock.newCondition();
/**
* 生产面包,加1
*
* @throws Exception
*/
public void increment() throws Exception {
lock.lock();
try {
//判断
while (number != 0) {
//等待面包被消费
condition.await();
}
//生产面包
number++;
System.out.println(Thread.currentThread().getName() + "\t " + number);
//通知消费者来消费面包
condition.signalAll();
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
/**
* 消费面包面包,减1
*
* @throws Exception
*/
public void decrement() throws Exception {
lock.lock();
try {
//判断
while (number == 0) {
//等待面包生产
condition.await();
}
//消费面包
number--;
System.out.println(Thread.currentThread().getName() + "\t " + number);
//通知生产者来生产面包
condition.signalAll();
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
public class TestProdConsumer {
public static void main(String[] args) {
ShareData shareData = new ShareData();
new Thread(() -> {
try {
for (int i = 0; i < 5; i++) {
shareData.increment();
}
} catch (Exception e) {
e.printStackTrace();
}
}, "AA").start();
new Thread(() -> {
try {
for (int i = 0; i < 5; i++) {
shareData.decrement();
}
} catch (Exception e) {
e.printStackTrace();
}
}, "BB").start();
new Thread(() -> {
try {
for (int i = 0; i < 5; i++) {
shareData.increment();
}
} catch (Exception e) {
e.printStackTrace();
}
}, "CC").start();
new Thread(() -> {
try {
for (int i = 0; i < 5; i++) {
shareData.decrement();
}
} catch (Exception e) {
e.printStackTrace();
}
}, "DD").start();
}
}
控制台效果图
阻塞队列实现生产者和消费者的线程通信 的代码
/*
* Copyright (C), 2013-2019, 天津大海云科技有限公司
*/
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* 生产消费模式(阻塞队列版本)
* 两个线程,一个生产面包,一个消费面包
*
* @author yangjikang
* @date 2019/6/17 17:33
* @modified By yangjikang
*/
class ShareData {
private volatile boolean flag = true;
private AtomicInteger atomicInteger = new AtomicInteger();
private BlockingQueue<Integer> blockingQueue = null;
//高手都用这种传接口的方式,这样可以适应7种实现类
public ShareData(BlockingQueue<Integer> blockingQueue) {
this.blockingQueue = blockingQueue;
//查看日志
System.out.println(blockingQueue.getClass().getName());
}
/**
* 生产面包,加1
*
* @throws Exception
*/
public void increment() throws Exception {
while (flag) {
int data = atomicInteger.incrementAndGet();
boolean offer = blockingQueue.offer(data,2L,TimeUnit.SECONDS);
if (offer) {
System.out.println(Thread.currentThread().getName() + "\t 生产成功..." + data);
} else {
System.out.println(Thread.currentThread().getName() + "\t 超时2秒没人消费,生产停止...");
return;
}
//等待一秒生产
TimeUnit.SECONDS.sleep(2);
}
System.out.println(Thread.currentThread().getName() + "\t 老板关店,生产停止!!!");
}
/**
* 消费面包面包,减1
*
* @throws Exception
*/
public void decrement() throws Exception {
while (flag) {
Integer poll = blockingQueue.poll(2L, TimeUnit.SECONDS);
if (poll == null) {
System.out.println("等了2秒钟没有面包了...走了...");
return;
}
System.out.println(Thread.currentThread().getName() + "\t 成功消费了" + poll);
}
}
public void Stop(){
this.flag = false;
}
}
public class TestProdConsumer {
public static void main(String[] args) throws InterruptedException {
ShareData shareData = new ShareData(new ArrayBlockingQueue<>(1));
new Thread(()->{
try {
shareData.increment();
} catch (Exception e) {
e.printStackTrace();
}
},"AA").start();
new Thread(()->{
try {
shareData.decrement();
} catch (Exception e) {
e.printStackTrace();
}
},"BB").start();
TimeUnit.SECONDS.sleep(5);
shareData.Stop();
}
}
控制台效果图