redis——队列

一、用list实现队列

rpush和lpop右进左出,lpush和rpop左进右出实现FIFO单向队列。

 1 public class QueueTest<T> extends AbstractQueue {
 2 
 3     private String qName;
 4 
 5     public QueueTest(String qName){
 6         this.qName = qName;
 7     }
 8 
 9     @Override
10     public Iterator iterator() {
11         throw new UnsupportedOperationException();
12     }
13 
14     @Override
15     public int size() {
16         return RedisUtils.llen(qName).intValue();
17     }
18 
19     @Override
20     public boolean offer(Object t) {
21         //String value = JSON.toJSONString(t);
22         return RedisUtils.rpush(qName,t.toString()) == 1;
23     }
24 
25     @Override
26     public String poll() {
27         return RedisUtils.lpop(qName);
28     }
29 
30     @Override
31     public String peek() {
32         return RedisUtils.lindex(qName,0L);
33     }
34 
35     public static void main(String[] args){
36         QueueTest queue = new QueueTest("queue");
37         queue.offer(1);
38         queue.offer(2);
39         queue.offer(3);
40         System.out.println("size : " + queue.size());
41         System.out.println("peek : " + queue.peek());
42         System.out.println(queue.poll());
43         System.out.println(queue.poll());
44         System.out.println(queue.poll());
45         System.out.println(queue.poll());
46         RedisUtils.close();
47     }
48 }

二、用zset实现延迟队列

 1 public class DelayQueueTest<E extends Delayed> extends AbstractQueue {
 2 
 3     private String qName;
 4     public DelayQueueTest(String qName){
 5         this.qName = qName;
 6     }
 7 
 8     @Override
 9     public Iterator iterator() {
10         throw new UnsupportedOperationException();
11     }
12 
13     @Override
14     public int size() {
15         return RedisUtils.zcard(qName).intValue();
16     }
17 
18     @Override
19     public boolean offer(Object o) {
20         //延时5s
21         return RedisUtils.zadd(qName,System.currentTimeMillis() + 5000,o.toString()) == 0;
22     }
23 
24     @Override
25     public String poll() {
26         Set<String> values = RedisUtils.zrangeByscore(qName,0, System.currentTimeMillis(),0,1);
27         if(values != null && !values.isEmpty()){
28             String value = values.iterator().next();
29             if(RedisUtils.zrem(qName,value) > 0){
30                 return value;
31             }
32         }
33         return null;
34     }
35 
36     @Override
37     public String peek() {
38         Set<String> values = RedisUtils.zrange(qName,0L,0L);
39         if (values != null && !values.isEmpty()){
40             String value = values.iterator().next();
41             return value;
42         }
43         return null;
44     }
45 
46     public static void main(String[] args) throws InterruptedException{
47         DelayQueueTest delayQueue = new DelayQueueTest("delayQueue");
48         Thread thread = new Thread(new Runnable() {
49             @Override
50             public void run() {
51                 for (int i = 0; i < 10; i++) {
52                     delayQueue.offer(i);
53                     try {
54                         Thread.sleep(1000);
55                     } catch (InterruptedException e) {
56                         e.printStackTrace();
57                     }
58                 }
59             }
60         });
61         thread.start();
62         Thread.sleep(10000);
63         thread.join();
64         for (;;){
65             if(delayQueue.peek() == null){
66                 break;
67             }
68             String value = delayQueue.poll();
69             if(value != null){
70                 System.out.println(value);
71             }
72             Thread.sleep(2000);
73         }
74         RedisUtils.close();
75     }
76 }

①、延迟队列空了,会无限peek 、poll重试,空轮询不但拉高了服务器的CPU消耗,Redis的QPS也会被拉高,可以让线程sleep一会儿

②、阻塞读,用brpop/blpop代替rpop/lpop,队列没有数据时,会立即进入休眠状态,一旦数据来了,立即醒过来。但空闲连接会自动断开,一直阻塞,闲置过久,会主动断开连接,此时brpop/blpop会抛出异常

posted on 2020-02-12 14:29  FFStayF  阅读(686)  评论(0编辑  收藏  举报