【20】阻塞队列原理

(1)一个人只要自己不放弃自己,整个世界也不会放弃你.
(2)天生我才必有大用
(3)不能忍受学习之苦就一定要忍受生活之苦,这是多么痛苦而深刻的领悟.
(4)做难事必有所得
(5)精神乃真正的刀锋
(6)战胜对手有两次,第一次在内心中.
(7)好好活就是做有意义的事情.
(8)亡羊补牢,为时未晚
(9)科技领域,没有捷径与投机取巧。
(10)有实力,一年365天都是应聘的旺季,没实力,天天都是应聘的淡季。
(11)基础不牢,地动天摇
(12)写博客初心:成长自己,辅助他人。当某一天离开人世,希望博客中的思想还能帮人指引方向.
(13)编写实属不易,若喜欢或者对你有帮助记得点赞+关注或者收藏哦~

阻塞队列原理

文章目录

  • 阻塞队列原理
    • 1.阻塞队列
      • 1.1队列
      • 1.2阻塞队列
      • 1.3JDK中专门的接口
      • 1.4阻塞队列在并发编程中用来做什么?
        • 1.4.1生产者与消费者模式
        • 1.4.2常用方法
        • 1.4.3常用阻塞队列
        • 1.4.4队列案例
        • 1.4.5延时队列的使用
    • 2.打赏鼓励
      • 2.1微信打赏
      • 2.2支付宝打赏

1.阻塞队列

1.1队列

(1)队列是一种数据结构,它有什么特征?

  • 它是一种先进先出的数据结构。

1.2阻塞队列

(1)管道头已经被堵住了,造成阻塞

(2)管道被填满了,造成阻塞

【20】阻塞队列原理_第1张图片

(1)当队列里面元素放满的时候,再往队列中存放元素的动作会造成阻塞。

(2)当队列里面的元素是空的时候,想从队列中拿元素的动作会造成阻塞。

1.3JDK中专门的接口

(1)BlockingDeque

public interface BlockingDeque<E> extends BlockingQueue<E>, Deque<E> {

【20】阻塞队列原理_第2张图片

(2)真正体现阻塞的方法为put与take,如果放入元素时队列已满,线程就会阻塞。如果取元素时队列已空,线程也会阻塞。

(3)BlockingDeque也有非阻塞方法

  • add与remove,如果放入元素时队列已满,抛出异常,如果从队列取出元素时,队列已空,也抛出异常。
  • offer与poll,poll如果放入元素时队列已满,抛出异常,如果从队列取出元素时,队列已空,返回null。

1.4阻塞队列在并发编程中用来做什么?

(1)用来解决生产者与消费者问题

(2)如果生产者生产速度很快,而消费者消费得很慢,生产者就需要等消费者把产品消费完了,才生产新的产品让消费者继续消费。

(3)如果消费者消费的速度要比生产者生产的速度要快,消费者要等待生产者生产出产品后再消费。

(4)这种情况下,为了平衡生产者与消费者之间能力上的不均衡的情况,则在生产者与消费者之间放入一个容器,生产者与消费者需要的产品,统一放在一个容器里面。

(5)生产者生产一个产品就往容器里面放一个,消费者消费一个就从容器里取出一个,这种在生产者与消费者之间引入一个中间容器的方式,就可以很好的平衡消费者与生产者之间一个性能不均衡的问题,让生产者与消费者实现解藕。

1.4.1生产者与消费者模式
1.4.2常用方法
1.4.3常用阻塞队列

【20】阻塞队列原理_第3张图片

(1)BlockingDeque已经为我们提供了很多实现。

(2)什么叫做有界,什么叫做无界?

  • 有界,即队列的长度是有限的,满了以后生产者就会阻塞。
  • 无界,可以不停的往队列里面放东西,而不会被阻塞。插入不阻塞,拿取还是会阻塞的,没有数据的时候也会阻塞。

(3)阻塞往队列里面插入元素可以阻塞,从队列里面取出元素也可以阻塞。

1.4.4队列案例
/**
 *类说明:存放的队列的元素,
 */
public class ItemVo<T> implements Delayed {

	//到期时间,但传入的数值代表过期的时长,传入单位毫秒
	private long activeTime;
	private T data;//业务数据,泛型

	//传入过期时长,单位秒,内部转换
	public ItemVo(long expirationTime, T data) {
		this.activeTime = expirationTime*1000+System.currentTimeMillis();
		this.data = data;
	}

	public long getActiveTime() {
		return activeTime;
	}

	public T getData() {
		return data;
	}

	/*
	 * 这个方法返回到激活日期的剩余时间,时间单位由单位参数指定。
	 */
	public long getDelay(TimeUnit unit) {
		long d = unit.convert(this.activeTime
				-System.currentTimeMillis(),unit);
		return d;
	}

	/*
	 *Delayed接口继承了Comparable接口,按剩余时间排序,实际计算考虑精度为纳秒数
	 */
	public int compareTo(Delayed o) {
		long d = (getDelay(TimeUnit.MILLISECONDS)
				- o.getDelay(TimeUnit.MILLISECONDS));
		if (d==0){
			return 0;
		}else{
			if (d<0){
				return -1;
			}else{
				return  1;
			}
		}
	}

}
/**
 *类说明:订单的实体类
 */
public class Order {
	private final String orderNo;//订单的编号
	private final double orderMoney;//订单的金额
	
	public Order(String orderNo, double orderMoney) {
		super();
		this.orderNo = orderNo;
		this.orderMoney = orderMoney;
	}

	public String getOrderNo() {
		return orderNo;
	}

	public double getOrderMoney() {
		return orderMoney;
	}	
}

/**
 *类说明:将订单推入队列
 */
public class PutOrder implements Runnable {
    private DelayQueue<ItemVo<Order>> queue;

    public PutOrder(DelayQueue<ItemVo<Order>> queue){
        this.queue = queue;
    }

	@Override
	public void run() {
		//5秒后到期
		Order orderTb = new Order("Tb12345",366);
		ItemVo<Order> itemTb = new ItemVo<Order>(5,orderTb);
		queue.offer(itemTb);
		System.out.println("订单5秒后超时:"+orderTb.getOrderNo()+";"
                +orderTb.getOrderMoney());
		//8秒后到期
		Order orderJd = new Order("Jd54321",366);
		ItemVo<Order> itemJd = new ItemVo<Order>(8,orderJd);
		queue.offer(itemJd);
		System.out.println("订单8秒后超时:"+orderJd.getOrderNo()+";"
                +orderJd.getOrderMoney());

	}	
}

/**
 *类说明:取出到期的订单的功能
 */
public class FetchOrder implements Runnable {
	private DelayQueue<ItemVo<Order>> queue;
	
    public FetchOrder(DelayQueue<ItemVo<Order>> queue){
        this.queue = queue;
    }

	@Override
	public void run() {
		while(true) {
			try {
				ItemVo<Order> item = queue.take();
				Order order = (Order)item.getData();
				System.out.println("Get From Queue:"+"data="
				+order.getOrderNo()+";"+order.getOrderMoney());
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		
	}	
}
1.4.5延时队列的使用
/**
 *类说明:延时队列测试程序
 */
public class Test {
    public static void main(String[] args) throws InterruptedException {
        DelayQueue<ItemVo<Order>> queue = new DelayQueue<ItemVo<Order>>();//延时队列

        new Thread(new PutOrder(queue)).start();
        new Thread(new FetchOrder(queue)).start();

        //每隔500毫秒,打印个数字
        for(int i=1;i<15;i++){
            Thread.sleep(500);
            System.out.println(i*500);
        }
    }
}

2.打赏鼓励

感谢您的细心阅读,您的鼓励是我写作的不竭动力!!!

2.1微信打赏

在这里插入图片描述

2.2支付宝打赏

在这里插入图片描述

你可能感兴趣的:(【20】阻塞队列原理)