前面有我写了个“传统生产消费者模式例子” 传统版需要自己控制等待,唤醒等操作细节同时需要兼顾效率和线程安全,而并发包下的BlockingQueue我们不需要关心什么时候需要阻塞线程,什么时候需要唤醒线程,因为这一切BlockingQueue都给一手包办了。
本例子所涉及到的知识点volatile/CAS/AtomicInteger/BlockQueue/线程交互/原子引用,需要了解详情可以看下我单独写的这些知识点文章,这里不过多叙述。
下面我们来看下例子:
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());
}
/**
* 生产
* @throws Exception
*/
public void myProd() throws Exception {
String data = null;
boolean retValue;
while (FLAG){
data = atomicInteger.incrementAndGet()+"";
retValue = blockingQueue.offer(data, 2L, TimeUnit.SECONDS);//保留2秒是为了看到效果
if(retValue){
System.out.println(Thread.currentThread().getName()+"\t 插入队列"+data+"成功");
}else {
System.out.println(Thread.currentThread().getName()+"\t 插入队列"+data+"失败");
}
TimeUnit.SECONDS.sleep(2);//同样是为了方便看效果2秒钟一次
}
System.out.println(Thread.currentThread().getName()+"\t 生产结束,表示FLAG = false");
}
/**
* 消费
* @throws Exception
*/
public void myConsumer() throws Exception {
String result = null;
while (FLAG){
result = blockingQueue.poll(2l, TimeUnit.SECONDS);//2秒钟取不到就不取了
if(null == result || result.equalsIgnoreCase("")){
FLAG = false;
System.out.println(Thread.currentThread().getName()+"\t 超过2秒没有取到值,消费退出。");
return;
}
System.out.println(Thread.currentThread().getName()+"\t 消费队列"+result+"成功");
}
}
public void stop(){
this.FLAG = false;
}
}
public class ConsumerBlockQueueDemo {
/**
* 例子所涉及到的知识点volatile/CAS/AtomicInteger/BlockQueue/线程交互/原子引用
* @param args
*/
public static void main(String[] args) {
MyResource myResource = new MyResource(new ArrayBlockingQueue<>(10));
new Thread(()->{
System.out.println(Thread.currentThread().getName()+"\t 生产线程启动");
try {
myResource.myProd();
} catch (Exception e) {
e.printStackTrace();
}
},"生产线程").start();
new Thread(()->{
System.out.println(Thread.currentThread().getName()+"\t 消费线程启动");
try {
myResource.myConsumer();
} catch (Exception e) {
e.printStackTrace();
}
},"消费线程").start();
//暂停5秒,后调用暂停生产
try {
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("5秒时间到,main线程叫停结束");
myResource.stop();
}
}
运行结果:

本文通过使用Java的BlockingQueue实现生产者消费者模式,详细介绍了如何利用volatile、CAS、AtomicInteger等技术确保线程安全及高效的数据交换。示例代码展示了如何在生产者和消费者线程间进行数据传递,并在特定条件下停止生产过程。
2001

被折叠的 条评论
为什么被折叠?



