阻塞隊列的使用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資源。

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