一. 阻塞队列版生产者消费者模式
1. 使用到的技术包括:
Volatile:保证可见性
CAS/AtomicInteger:保证原子性
BlockingQueue:保证并发性
2. 集合了前面几篇文章的精华:
1. 了 解 Volatile
2. 了 解 CAS
3. 了 解 AtomicReference
4. 了 解 阻塞队列
5. 了 解 传统生产者消费者模式
3. 阻塞队列版生产者消费者模式:
代码演示
//资源类
class MySource {
//标识 volatile保证线程之间的可见性,保证多线程并发进行
private volatile boolean FLAG = true; //默认开启,开始进行生产+消费
//在多线程下使用 i++,是在给自己埋雷,使用原子整形
private AtomicInteger atomicInteger = new AtomicInteger(); //默认值为 0
//传接口,不传具体实现类,为了更好的适配,更通用
BlockingQueue<String> blockingQueue = null;
//有参构造
public MySource(BlockingQueue<String> blockingQueue) {
this.blockingQueue = blockingQueue;
//可以获得具体传入的是什么阻塞队列类
System.out.println(blockingQueue.getClass().getName());
}
//生产者
public void prod() throws Exception {
String data = null;
boolean res;
//判断
while (FLAG) {
data = atomicInteger.incrementAndGet() + "";
//添加数据
res = blockingQueue.offer(data, 2L, TimeUnit.SECONDS);
if (res) {
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() + "生产结束 FLAG: false ");
}
//消费者
public void consumer() throws Exception {
String result = null;
//判断
while (FLAG) {
//取数据
result = blockingQueue.poll(2L, TimeUnit.SECONDS);
if (null == result || result.equalsIgnoreCase("")) {
//如果队列里面没有数据了,可以把标识设置为false
FLAG = false;
System.out.println(Thread.currentThread().getName() + "\t 队列里面没有数据可以消费了,退出。。。");
return;
}
System.out.println(Thread.currentThread().getName() + "\t 移出数据 " + result + " 成功");
}
System.out.println(Thread.currentThread().getName() + "消费结束 FLAG: false ");
}
//停止生产消费模式
public void stop() throws Exception {
this.FLAG = false;
}
}
调用
public static void main(String[] args) throws Exception {
//操作资源类
MySource mySource = new MySource(new ArrayBlockingQueue<>(5));
//生产线程
new Thread(() -> {
try {
System.out.println(Thread.currentThread().getName() + "生产线程启动。。。");
mySource.prod();
} catch (Exception e) {
e.printStackTrace();
}
}, "Producer").start();
//消费线程
new Thread(() -> {
try {
System.out.println(Thread.currentThread().getName() + "消费线程启动。。。");
mySource.consumer();
} catch (Exception e) {
e.printStackTrace();
}
}, "Consumer").start();
//5秒后停止生产消费模式
try { TimeUnit.SECONDS.sleep(5); } catch (InterruptedException e) { e.printStackTrace(); }
System.out.println();
System.out.println();
System.out.println();
System.out.println("5秒时间到,停止。");
mySource.stop();
}
运行结果