java.lang.Long cannot be cast to java.util.List Jedis多线程环境下使用方案

最近在做基于netty的聊天室,消息接收和发送使用了netty,业务处理又引入了Disruptor,再加上项目中对外的接口也使用了redis,此后Jedis访问redis就会经常报错。

    java.lang.ClassCastException: java.lang.Long cannot be cast to java.util.List
    at redis.clients.jedis.Connection.getRawObjectMultiBulkReply(Connection.java:230)
    at redis.clients.jedis.Connection.getObjectMultiBulkReply(Connection.java:236)

 最开始以为是redis服务的问题,后来查阅文章和自己分析报错发现这个错误是多线程环境下引发的问题。

因为redis的一大特性就是单线程,Jedis在设计上也就使用了单线程访问redis,如果在多线程的环境下调用,就会引发返回结果类型的混乱,因此Jedis在使用中不能仅仅为单例模式,但是每次使用new一个Jedis对象又过于消耗资源,因此Jedis提供了一个JedisPool的类用来池化Jedis对象。

我通过网上的资料和自己的实际情况整合了一个工具类,以下是源码:

 

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

import java.util.Set;
import redis.clients.jedis.params.SetParams;

public class DoMyJedis {

    private static final Logger log = LoggerFactory.getLogger(DoMyJedis.class);

    //内部类组成单例模式

    private JedisPool pool;
    static enum SingletonEnum{
        //创建一个枚举对象,该对象天生为单例
        INSTANCE;
        private JedisPool pool;
        //私有化枚举的构造函数
        private SingletonEnum(){
            pool=new JedisPool(new JedisPoolConfig(), ConfigFactory.RedisIP,6379);
        }
        public JedisPool getInstnce(){
            return pool;
        }
    }

    //这三个方法,包括getInstance,不对外提供,仅在封装常用操作时使用
    private static JedisPool getInstance(){
        return SingletonEnum.INSTANCE.getInstnce();
    }
    private static Jedis GetNewJedis(){
        return getInstance().getResource();
    }
    private static void CloseJedis(Jedis jedis){
        if(jedis!=null){
            jedis.close();
        }
    }



    //封装jedis常用操作
    public static String get(String key){
        Jedis jedis=null;
        try {
            jedis=GetNewJedis();
            String value= jedis.get(key);
            return value;
        }catch (Exception e){
            log.error("Jedisget",e);
        }finally {
            CloseJedis(jedis);
        }
        return null;
    }

    public static String set(String key, String kvalue, SetParams setParams){
        Jedis jedis=null;
        try {
            jedis=GetNewJedis();
            String value= jedis.set(key,kvalue,setParams);
            return value;
        }catch (Exception e){
            log.error("Jedisget",e);
        }finally {
            CloseJedis(jedis);
        }
        return null;
    }

    public static Long sadd(String key,String member){
        Jedis jedis=null;
        try {
            jedis=GetNewJedis();
            Long value= jedis.sadd(key,member);
            return value;
        }catch (Exception e){
            log.error("Jedissadd",e);
        }finally {
            CloseJedis(jedis);
        }
        return null;
    }
    public static Set smembers(String key){
        Jedis jedis=null;
        try {
            jedis=GetNewJedis();
            Set value= jedis.smembers(key);
            return value;
        }catch (Exception e){
            log.error("Jedisget",e);
        }finally {
            CloseJedis(jedis);
        }
        return null;
    }

    public static Long srem(String key,String member){
        Jedis jedis=null;
        try {
            jedis=GetNewJedis();
            Long value= jedis.srem(key,member);
            return value;
        }catch (Exception e){
            log.error("Jedissrem",e);
        }finally {
            CloseJedis(jedis);
        }
        return null;
    }

}

用枚举实现单例模式,并封装常用操作,如果有需要添加的方法,复制修改即可。

程序调用使用DoMyJedis.get(key)即可。

你可能感兴趣的:(开源项目研究,Redis,Jedis)