java.lang.ClassCastException: 当使用Redis时,B不能被投向java.util.List。

问题描述 投票:0回答:1

我有下面的代码。

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)

如果我再次运行相同的代码,它以相同的数据运行正常。不明白为什么会出现这样的问题。

java redis classcastexception
1个回答
-1
投票

TL;DR

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

解释

我看到了这些完全相同的异常,当我试图找出问题时,我遇到了一个类似的 关于绝地武士项目的问题 解释Jedis是不安全的线程。

由于我在搜索这个同样的例外情况时发现了这个问题,我将分享一些我的特殊情况的细节,所以它可能会帮助未来的读者。

在我的特殊情况下,我把 SCAN 命令使用 RedisTemplate 从Spring Data Redis中调用。我正在对产生的 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();
    });
}

© www.soinside.com 2019 - 2024. All rights reserved.