java.lang.ClassCastException:[使用Redis时,不能将B强制转换为java.util.List

时间:2016-01-18 11:27:02

标签: java redis classcastexception

我有以下代码:

jedis.mget(objects.toArray(new String[objects.size()]));

其中objects是一个字符串列表。代码在大多数情况下运行良好。但是出现意外情况后会出现异常情况。

java.lang.ClassCastException: [B cannot be cast to java.util.List
at redis.clients.jedis.Connection.getBinaryMultiBulkReply(Connection.java:221)
at redis.clients.jedis.Connection.getMultiBulkReply(Connection.java:214)
at redis.clients.jedis.Jedis.mget(Jedis.java:383)

如果我再次运行相同的代码,它会运行相同的数据。无法理解此类问题的原因。

1 个答案:

答案 0 :(得分:-1)

TL; DR

Jedis实例不是线程安全的,跨多个线程对Jedis实例的调用将导致这些类型的错误。尝试切换为使用JedisPool来管理连接的创建。

说明

我看到了这些完全相同的异常,并且在试图找出问题时,我遇到了类似的issue on the Jedis project解释杰迪斯不是线程安全的。

由于我在搜索同一例外时发现了这个问题,因此我将分享我的特殊情况的一些细节,以便为将来的读者提供帮助。

在我的特定情况下,我使用Spring Data Redis中的SCAN调用RedisTemplate命令。我正在连接生命周期之外调用生成的Cursor

我的原始代码如下。

public Long size() {
    Cursor<byte[]> scan =  redisTemplate.execute((RedisConnection connection) -> connection.scan(ScanOptions.scanOptions().match(prefix + "*").build()));
    AtomicLong count = new AtomicLong();
    scan.forEachRemaining(bytes -> count.getAndIncrement());
    return count.get();
}

稍作更改后,我发现执行此操作的正确方法是简单地将光标交互移动到执行lambda内。

public Long size() {
    return redisTemplate.execute((RedisConnection connection) -> {
        Cursor<byte[]> scan = connection.scan(ScanOptions.scanOptions().match(prefix + "*").build());
        AtomicLong count = new AtomicLong();
        scan.forEachRemaining(bytes -> count.getAndIncrement());
        return count.get();
    });
}