kagamihogeの日記

kagamihogeの日記です。

Jedisで単一コネクションをマルチスレッドで使用してはいけない

JedisJavaのRedisクライアント。自明だが、単一コネクションをマルチスレッドで使いまわすとその動作は不定となる。

とりあえずソースコード

package kagamihoge.jedissample;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import redis.clients.jedis.Jedis;

public class NoPool {
    static Jedis jedis = new Jedis("localhost", 16379);

    public static void main(String[] args) {
        ExecutorService pool = Executors.newFixedThreadPool(10);

        pool.submit(new TTask("a0"));
        pool.submit(new TTask("a1"));
    }

    static class TTask implements Runnable {
        public String a;

        public TTask(String a) {
            super();
            this.a = a;
        }

        @Override
        public void run() {
            while (true) {
                for (int i = 0; i < 100; i++) {
                    System.out.println(jedis.set(a + i, "v"));
                    System.out.println((a + i) + jedis.get(a + i));
                }
            }
        }
    }
}

これを実行すると……何も起きない。何が起きているかまでは調べる気は無いが、ともかくやってはいけない、という事だけは分かる。

というわけでJedisPoolを使用する。

package kagamihoge.jedissample;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;

public class Pooling {
    static JedisPool jedisPool = new JedisPool("localhost", 16379);

    public static void main(String[] args) {
        ExecutorService pool = Executors.newFixedThreadPool(10);

        pool.submit(new TTask("a0"));
        pool.submit(new TTask("a1"));
        pool.submit(new TTask("a2"));
        pool.submit(new TTask("a3"));
        pool.submit(new TTask("a4"));
        pool.submit(new TTask("a5"));
        pool.submit(new TTask("a6"));
        pool.submit(new TTask("a7"));
        pool.submit(new TTask("a8"));
        pool.submit(new TTask("a9"));
    }

    static class TTask implements Runnable {

        public String a;

        public TTask(String a) {
            super();
            this.a = a;
        }

        @Override
        public void run() {
            while (true) {
                for (int i = 0; i < 100; i++) {
                    try (Jedis jedis = jedisPool.getResource()) {
                        System.out.println(jedis.set(a + i, "v"));
                        System.out.println((a + i) + jedis.get(a + i));
                    }
                }
            }
        }
    }
}

これは動作する。

なお、上はメチャクチャ適当な使い方なのでJedis - Getting Startedのusing Jedis in a multithreaded environmentを最低限読んでから使うのが良い。