记录三个小时踩的一个坑 延时消息队列 生产者消费者模式

手动设计一个延时队列,需要用到delayqueue,AtomicInteger等多线程知识。按照生产者消费者模式设计。

因为我在测试timeunit枚举类时候,忘记统一单位导致后面程序可以正常运行,就是得不到正确结果。解决方法,统一时间单位,

将TimeUnit.MINUTES修改为TimeUnit.MILLISECONDS

 

总结:再查找可以正常运行无报错的程序的bug时候

1    尝试分块进行测试,确保分块测试没问题

2    找到正确实例,分块将自己的代码块带入正确实例进行替换验证,确保每块代码块可以正常运行,

3    找到正确实例,分块(块可以从大到小)将正确实例带入自己代码中,直到找到可以保证正常运行的代码位置,对比两者区别

现在将正确代码共享

package javatest;

import java.text.DateFormat;
import java.util.Date;
import java.util.Random;
import java.util.concurrent.DelayQueue;
import java.util.concurrent.Delayed;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

public class MyDelayQueue {
	
	//线程安全的,自动产生编号
	static AtomicInteger messageno = new AtomicInteger(1);

	public static void main(String[] args) {

		DelayQueue<DelayQueueItem> queue = new DelayQueue<>();
		producer(queue,"生产者1");
		producer(queue,"生产者2");
		producer(queue,"生产者3");
		producer(queue,"生产者4");
		consumer(queue);
		consumer(queue);
		consumer(queue);

		
	
	}
	
	private static void consumer(DelayQueue<DelayQueueItem> queue) {
		new Thread(new Runnable() {
			@Override
			public void run() {
				while(true) {
					DelayQueueItem item = null;
					try {
						item = queue.take();
						System.out.println(item.toString());
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
			}
		}).start();
	}

	private static void producer(DelayQueue<DelayQueueItem> queue, String name) {
		new Thread() {
			@Override
			public void run() {
				while(true) {
					Long time = 100L*(new Random().nextInt(10) + 1);
					
					//适当延时,不至于插入队列太快
					try {
						Thread.sleep(3000);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					
					String message = String.format("队列名:%s,消息编号:%d,发送时间:%s,延时时间:%s 毫秒", 
							name,	//队列名字,由main传过来
							messageno.getAndIncrement(),	//由全局变量传来,这个变量线性安全,类似于i++
							DateFormat.getDateTimeInstance().format(new Date()),	//java8新增加的时间函数
							time);
					DelayQueueItem item = new DelayQueueItem(time,message);
					queue.put(item);
					//System.out.println("test:"+item.toString());
					
				}
			}
		}.start();
	}

	static class DelayQueueItem implements Delayed {
		//delayqueue规定放入队列中的元素必须实现delayed接口并且重写方法
		//每个元素的超时时间(延时时间)
		Long time = System.currentTimeMillis();
		//放入队列的消息体
		String message;
		
		public DelayQueueItem() {
			super();
		}

		public DelayQueueItem(Long time, String message) {
			super();
			this.time += time;
			this.message = message;
		}

		
		//timeunit枚举类提供一些时间计算函数,
		//convert函数计算延时时间,返回Long类型。(this.time - System.currentTimeMillis())*TimeUnit.MILLISECONDS
		//其中 TimeUnit.MILLISECONDS  = 1 	表示参与运算的单位是毫秒
		//   TimeUnit.SECONDS = 1000 		
		//   TimeUnit.MINUTES = 6000 
		//   TimeUnit.HOURS = 3600000
		@Override
		public long getDelay(TimeUnit unit) {
			// TODO Auto-generated method stub
			return unit.convert(this.time - System.currentTimeMillis(), TimeUnit.MILLISECONDS);
		}
		
		//接受运用delayed类型,属于多态的一种体现
		//compareTo函数为排序提供了比较策略,这个属于类外比较
		@Override
		public int compareTo(Delayed o) {
			// TODO Auto-generated method stub
			if (this.getDelay(TimeUnit.MILLISECONDS)>o.getDelay(TimeUnit.MILLISECONDS)) return 1;
			else if  (this.getDelay(TimeUnit.MILLISECONDS)<o.getDelay(TimeUnit.MILLISECONDS)) return -1;
			return 0;
		}

		@Override
		public String toString() {
			return "time=" + time + ", message=" + message + "]";
		}
		
		
	}
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值