直接上代码: 前提是你已经 熟悉了原子类,volatile,和阻塞队列
public class JucPCdemo03 {
/**
* 阻塞队列的应用: 这里实现的生产者消费者,生产一个消费一个
* 且,不使用 synchronized 和 lock锁
*/
private volatile boolean flag = true;
private static AtomicInteger atomicInteger = new AtomicInteger(0);
private BlockingQueue<String> blockingQueue;
public JucPCdemo03(BlockingQueue<String> blockingQueue) {
this.blockingQueue = blockingQueue;
System.out.println(blockingQueue.getClass().getName());
}
//生产方法
public void producer() throws InterruptedException {
String data = null;
boolean result;
while(flag){
data = atomicInteger.incrementAndGet()+"";
result = blockingQueue.offer(data, 2, TimeUnit.SECONDS);
if(result){
System.out.println(Thread.currentThread().getName() + "--生产者--添加队列成功--data:" + data);
}else{
System.out.println(Thread.currentThread().getName() + "--生产者--超出等待时间, 退出等待");
}
//我在这里有疑惑? : 你能帮我解决么?
// 这里睡1秒,不能少,因为 atomicInteger加1的操作是原子的,加入阻塞队列的操作是并发的,会导致同一时间内,有多个元素加入到了阻塞队列中,返回都是true,即使规定阻塞队列容量为1,
// 所以这里的疑惑是: 阻塞队列容量为1, 并发情况下,却多个数据都加入队列成功了?为什么
TimeUnit.SECONDS.sleep(1);
}
System.out.println();
System.out.println();
System.out.println();
System.out.println("生产者停止生产了");
}
//消费方法
public void consumer() throws InterruptedException {
String data = null;
while(flag){
data = blockingQueue.poll(2, TimeUnit.SECONDS);
if(null == data || "".equals(data)){
System.out.println(Thread.currentThread().getName() + "--消费者--超出等待时间.退出等待,消费停止");
flag = false;
return;
}else{
System.out.println(Thread.currentThread().getName() + "--消费者--消费成功,消费的数据为: data:" + data);
}
}
System.out.println();
System.out.println();
System.out.println();
System.out.println("消费者停止消费了");
}
public void stop(){
flag = false;
}
public static void main(String[] args) throws InterruptedException {
JucPCdemo03 jucPCdemo03 = new JucPCdemo03(new ArrayBlockingQueue<>(1));
new Thread(()->{
try {
jucPCdemo03.producer();
} catch (InterruptedException e) {
e.printStackTrace();
}
},"生产者线程启动").start();
new Thread(()->{
try {
jucPCdemo03.consumer();
} catch (InterruptedException e) {
e.printStackTrace();
}
},"消费者线程启动").start();
TimeUnit.SECONDS.sleep(5);
jucPCdemo03.stop();
}
}
运行结果:
如果把生产者的 睡一秒, 注释掉, 会是另一种结果, 生产者生产的data 都很大,是因为一直再while循环中,不停的自增, 但是同时3个数据加入队列成功,可是队列的容量设置是1啊, 这个结果让我有些疑惑, 你能帮我解惑么?
后来想到: 阻塞队列类本身是juc包下的, 肯定是原子性操作的, 所以他的容量前后都是始终为1, 是因为 "生产者线程启动--生产者--添加队列成功--data:269209" 这句话打印,这里并发打印了, 所以给我看到的假象多个数据都加入阻塞队列成功了, 于是验证: 加一行代码,
运行结果为: 队列容量始终为1, "生产者线程启动--生产者--添加队列成功--data:269209" 这句话有时候打印三次,有时候打印一次,很明显验证了我的结论