Search code examples
springjunitredisspring-data-redisjedis

RedisTemplate multi thread not work, why and how to fix?


I want to use RedisTemplate, more specific StringRedisTemplate in Junit used with multi thread, but it fails. And if I use only test thread, it work. Why? Isn't StringRedisTemplate thread safe? How to fix that?

@Test
void multiThreadStringRedisTemplate(@Autowired RedisConnectionFactory redisConnectionFactory){
        Runnable runnable = () -> {
            StringRedisTemplate stringRedisTemplate = new StringRedisTemplate(redisConnectionFactory);
            for(int i = 0;i < 50;++i){
                String value = stringRedisTemplate.opsForValue().get("ok");
                System.out.println(i + ":" + value);
            }
        };
        // multi thread not work
        ExecutorService executorService = Executors.newCachedThreadPool();
        for(int i = 0;i < 1;++i){
            executorService.execute(runnable);
        }
        // runnable.run(); this work fine
    }

I try to use spring's RedisTemplate in multi thread, but not work. The test process just exit with 0 without any exception info.

pom's dependency and properties.yml as:

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
            <exclusions>
                <exclusion>
                    <artifactId>lettuce-core</artifactId>
                    <groupId>io.lettuce</groupId>
                </exclusion>
            </exclusions>
        </dependency>
        
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
        </dependency>
        
        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
        </dependency>
    </dependencies>

I've enabled the connection poll with default configuration.

spring:
  redis:
    host: ${romote_host}
    port: 6379
    password: ${password}
    database: 0
    connect-timeout: 3000ms
    jedis:
      pool:
        enabled: true 

Solution

  • You need to wait for other threads in your executor service to do their work. I think adding this snippet at the end of your test would suffice

    taskExecutor.shutdown();
    try {
      taskExecutor.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
    } catch (InterruptedException e) {
      ...
    }