(1)一个人只要自己不放弃自己,整个世界也不会放弃你.
(2)天生我才必有大用
(3)不能忍受学习之苦就一定要忍受生活之苦,这是多么痛苦而深刻的领悟.
(4)做难事必有所得
(5)精神乃真正的刀锋
(6)战胜对手有两次,第一次在内心中.
(7)好好活就是做有意义的事情.
(8)亡羊补牢,为时未晚
(9)科技领域,没有捷径与投机取巧。
(10)有实力,一年365天都是应聘的旺季,没实力,天天都是应聘的淡季。
(11)基础不牢,地动天摇
(12)写博客初心:成长自己,辅助他人。当某一天离开人世,希望博客中的思想还能帮人指引方向.
(13)编写实属不易,若喜欢或者对你有帮助记得点赞+关注或者收藏哦~
阻塞队列原理
文章目录
1.阻塞队列
1.1队列
(1)队列是一种数据结构,它有什么特征?
- 它是一种先进先出的数据结构。
1.2阻塞队列
(1)管道头已经被堵住了,造成阻塞
(2)管道被填满了,造成阻塞
(1)当队列里面元素放满的时候,再往队列中存放元素的动作会造成阻塞。
(2)当队列里面的元素是空的时候,想从队列中拿元素的动作会造成阻塞。
1.3JDK中专门的接口
(1)BlockingDeque
public interface BlockingDeque<E> extends BlockingQueue<E>, Deque<E> {
(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常用阻塞队列
(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.打赏鼓励
感谢您的细心阅读,您的鼓励是我写作的不竭动力!!!