阻塞队列的使用Demo

谈到阻塞队列需要谈到以往的lock中的await和signel,以往线程的状态需要我们手动修改来完成线程间的调度,此时BlockingQueue阻塞队列横空出世,即线程状态的挂起和唤醒状态都由该队列内部完成,你用即可,该队列在多线程场景下,可以很好的实现生产和消费的模式,其实消息中间件底层用的就是该队列。

BlockingQueue核心的方法就是offer和poll,即放和拿,不传参意为拿不到或放不进消息我就一种等,直到拿到消息,要是传参,即我也是有限度的,等了那么久还没放入或拿到那我就停了。

package com.reentralock;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

class MySource{//资源类
	
	private volatile boolean flag = true;//全网开关
	private AtomicInteger atomicInteger =new AtomicInteger();
	
	private BlockingQueue<String> queue = null;//留着给别人用的队列,口子要大,传它的子类全可以

	public MySource(BlockingQueue<String> queue) {
		super();
		this.queue = queue;
		System.out.println(queue.getClass().getName());//日志打印细粒度
	}
	
	public void myProduct() throws Exception{
		
		String data = "";
		boolean result;
		//1.判断
		while(flag){
			data = atomicInteger.incrementAndGet()+"";
			result = queue.offer(data, 2, TimeUnit.SECONDS);//2s加不进去不加了
			
			if(result){
				System.out.println("生产cake"+data+"成功");
			}else{
				System.out.println("生产cake"+data+"失败");
			}
			TimeUnit.SECONDS.sleep(1);//生产间隔1s
		}
		
		System.out.println("boss叫停,别再生产了!");
	}
	
	public void myConsumer() throws Exception{
		
		String data = "";
		
		//1.判断
		while(flag){
			data = queue.poll(2, TimeUnit.SECONDS);//两秒钟拿不到,我就不拿了
			 if(null == data || "".equals(data)){
				 System.out.println("队列中无cake可消费");
				 flag = false;
				 System.out.println("2s未拿到cake,停止拿");
				 return;//跳出方法
			 }else{
				 System.out.println("消费cake"+data+"成功");
			 }
		}
		System.out.println("boss叫停,别再生产了!");
	}
	
	public void stop(){//boss让你停 你就停
		flag = false;
	}
}
/**
 * 队列高级版,阻塞队列将挂起、唤醒 内部实现,你用即可
 * 
 * 模仿场景,多线程下,只需一个标志位,控制整个消费和生产的实现,消费者和生产者的来源于去处需要队列暂存
 * 多线程下标配:Atomic、BlockQueue、CAS、Volatile =abcv
 * 
 * 多线程
 * 上联:线程操作资源类
 * 下联:判断干活再通知(注意虚假唤醒)= 针对lock而言
 * 横批:BlockQueue属顶级
 * 
 * @author 英俊
 *
 */
public class BlockQueueDemo {

	public static void main(String[] args) {
		
		MySource mySource =new MySource(new ArrayBlockingQueue<>(10));
		
		new Thread(()->{
			System.out.println(Thread.currentThread().getName()+"\t 生产线程启动");
			try {
				mySource.myProduct();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}, "product").start();
		
		new Thread(()->{
			System.out.println(Thread.currentThread().getName()+"\t 消费线程启动");
			try {
				mySource.myConsumer();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}, "consumer").start();
		
		
		try {
			TimeUnit.SECONDS.sleep(5);
			System.out.println("boss 5s叫停!!");
			mySource.stop();//5s main主线程叫停!!
		} catch (InterruptedException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
	}

}

放心:一直poll拿不到消息,不会占用cpu资源。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章