Java线程实现Redis任务队列(生产者消费者)

注:接上篇IDEA整合Redis,本篇实现Redis的任务队列,Redis连接池具体配置看上篇。

一:写一个Jedis的工具类JedisUtil,将Jedis中的部分方法实现,代码如下:

package com.wq.Util;
import com.wq.RedisPool.RedisPool;
import redis.clients.jedis.Jedis;
import java.util.List;
public class JedisUtil {
    private static Jedis jedis = null;
    /**
     * 存储REDIS队列 顺序存储
     * @param key 字节类型
     * @param value 字节类型
     */
    public static void lpush(byte[] key,byte[] value){
        try {
            jedis = RedisPool.getJedis();
            jedis.lpush(key,value);
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            RedisPool.returnResource(jedis);
        }
    }
    /**
     * 存储REDIS队列 反序存储
     * @param key 字节类型
     * @param value 字节类型
     */
    public static void rpush(byte[] key,byte[] value){
        try {
            jedis = RedisPool.getJedis();
            jedis.rpush(key,value);
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            RedisPool.returnResource(jedis);
        }
    }
    /**
     * 移除列表的最后一个元素,并将该元素添加到另一个列表并返回,就可以实现任务队列
     * @param srckey 原队列的key
     * @param dstkey 目标队列的key
     */
    public static byte[] rpoplpush(byte[] srckey,byte[] dstkey){
        byte[] value = null;
        try {
            jedis = RedisPool.getJedis();
            value= jedis.rpoplpush(srckey,dstkey);
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            RedisPool.returnResource(jedis);
        }
        return value;
    }
    /**
     * 从列表中弹出一个值,将弹出的元素插入到另外一个列表中并返回它; 如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止。
     * @param srckey
     * @param dstkey
     * @param timout
     * @return
     */
    public static byte[] brpoplpush(byte[] srckey,byte[] dstkey,int timout){
        byte[] value = null;
        try {
            jedis = RedisPool.getJedis();
            value = jedis.brpoplpush(srckey,dstkey,timout);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            RedisPool.returnResource(jedis);
        }
        return value;
    }
    /**
     * 设置实现任务队列的键和过期时间
     * @param key
     * @param timeout
     */
    public static List<byte[]> brpop(byte[] key, int timeout){
        List<byte[]> result = null;
        try {
            jedis = RedisPool.getJedis();
            result=jedis.brpop(0,key);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            RedisPool.returnResource(jedis);
        }
        return result;
    }
    /**
     * 移除队列中的最后一个元素并显示最后一个元素
     * @param key
     * @return
     */
    public static byte[] rpop(byte[] key) {
        byte[] bytes = null;
        try {
            jedis = RedisPool.getJedis();
            bytes = jedis.rpop(key);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            RedisPool.returnResource(jedis);
        }
        return bytes;
    }
}
二:写一个实体类MessageUtil,实现存入Redis中的是对象,不是单单的基本类型,存入Redis中的对象需要实现序列化接口,代码如下:

package com.wq.Util;
import java.io.Serializable;
public class MessageUtil implements Serializable{
    private static final long serialVersionUID = -8785806144878640550L;
    private int id;
    private String content;
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getContent() {
        return content;
    }
    public void setContent(String content) {
        this.content = content;
    }
}
三:使用两个Redis列表,一个队列作为生成者,一个队列作为消费者,加上线程实现两个列表,一个列表产生任务,通过任务队列,另一个列表处理任务,代码如下:

1.使用jedis中的flushAll方法,将Redis数据库中的所有key清空:

Java线程实现Redis任务队列(生产者消费者)_第1张图片

控制台信息说明,两个队列都不存在了;

2.再使用initList类,创建一个列表,并将对象序列化过后存入列表,并有线程持续产生对象并插入列表,代码如下:

package com.wq.Util;
import com.wq.RedisPool.RedisPool;
import redis.clients.jedis.Jedis;
public class initList {
    public static byte[] rediskey = "key".getBytes();
    public static byte[] dstkey = "dstkey".getBytes();
    public static long time=0;
    public static int i=0;
    public static void main(String args[]) {
        Jedis jedis = RedisPool.getJedis();
      while (true){
          try {
              MessageUtil msg1 = new MessageUtil();
              msg1.setId(i);
              msg1.setContent("wq"+i);
              JedisUtil.lpush(rediskey,SerialoizebleUtil.serialize(msg1));
              time=2000;
              System.out.println("success"+i);
              System.out.println(jedis.lrange(rediskey,0,100));
              i++;
              Thread.sleep(time);
          } catch (InterruptedException e) {
              e.printStackTrace();
          }
      }
    }
}
控制台输出如下,说明一直在向列表中插入新产生的对象,这里插入了6个对象后,停止线程:
 
  

Java线程实现Redis任务队列(生产者消费者)_第2张图片

2.再开启一个线程,使用Redis中的brpoplpush方法,实现任务队列原理,代码如下:

package com.wq.Util;
import com.wq.RedisPool.RedisPool;
import junit.framework.TestCase;
import redis.clients.jedis.Jedis;
public class JedisUtilTest extends TestCase {
    public static byte[] rediskey = "key".getBytes();
    public static byte[] dstkey = "dstkey".getBytes();
    public static long time=0;
    public static void main(String args[]){
        Jedis jedis = RedisPool.getJedis();
        while (true) {
            try {
                byte[] bytes = JedisUtil.brpoplpush(rediskey, dstkey, 0);
                MessageUtil msg = (MessageUtil) SerialoizebleUtil.unSerialize(bytes);
                if (msg != null) {
                    System.out.println(msg.getId() + " " + msg.getContent());
                }
                time=3000;
                System.out.println(jedis.lrange(rediskey,0,100));
                System.out.println(jedis.lrange(dstkey,0,100));
                Thread.sleep(time);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
控制台输出如下:

Java线程实现Redis任务队列(生产者消费者)_第3张图片

上面的列表存的是刚才产生的6个对象,下面圈出来的是新的列表,可以看出新的列表的对象在递增,说明成功实现了任务队列原理,下面是全部完成了的图片


这里将两个线程同时启动,更容易理解任务队列以及生产者消费者概念。


To  be continue..........

你可能感兴趣的:(个人学习记录)