I'm using redis
with the help of jedis
client. Attaching the code snippet for key value set/get here. Here I'm expecting my jedisPool
to get initialised only once but it is getting initialised multiple times. Not sure where I'm going wrong. Scratching my head for several days with it. I have no clues why it does multiple initialisation.
//$Id$
package experiments.with.truth;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
public class RedisClientUtil {
private static JedisPool pool; //I persume the deafult value initialised in my static variable would be null
static int maxActiveConnections = 8;
static int maxWaitInMillis = 2000;
static String host = "127.0.0.1";
static int port = 6379;
static int REDIS_DB = 1;
public static void initRedisClient() throws Exception {
try {
Class classObj = Class.forName("redis.clients.jedis.JedisPool");
if (classObj != null && pool == null) {
JedisPoolConfig jedisConfig = new JedisPoolConfig();
jedisConfig.setMaxTotal(maxActiveConnections);
jedisConfig.setMaxWaitMillis(maxWaitInMillis);
pool = new JedisPool(jedisConfig, host, port);
System.out.println("Pool initialised successfully !");
}
} catch(ClassNotFoundException ex) {
System.out.println("Couldn't initialize redis due to unavailability of jedis jar in your machine. Exception : " + ex);
}
}
public Jedis getJedisConnection() {
if(pool == null) {
initRedisClient();
}
return pool.getResource();
}
private static void returnJedis(Jedis jedis) {
try {
pool.returnResource(jedis);
} catch(Exception ex) {
ex.printStackTrace();
}
}
public static String getValue(String key) throws Exception{
Jedis jedisCon = null;
try {
jedisCon = getJedisConnection();
jedisCon.select(REDIS_DB);
String val = jedisCon.get(key);
return val;
} catch (Exception e) {
e.printStackTrace();
} finally {
if (jedisCon != null) {
returnJedis(jedisCon);
}
}
return null;
}
public void addValueToRedis(String key, String value) {
Jedis jedisCon = null;
try {
jedisCon = getJedisConnection();
jedisCon.select(REDIS_DB);
jedisCon.set(key, value);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (jedisCon != null) {
returnJedis(jedisCon);
}
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.println("Value : " + getValue("a"));
System.out.println("Value : " + getValue("b"));
System.out.println("Value : " + getValue("c"));
}
}
I could see this debug log Pool initialised successfully
multiple times when my program runs. Can someone help me find the loophole in this? Or how could I make this better (or make to behave it as expected) by initialising only once throughout the entire program.
Looks like a basic multithreading case. Your app asks for 5 connections in a short time. All of them see that pool==null and proceed initializing it.
Easy solution: public static synchronized void initRedisClient() throws Exception {
update and private static volatile JedisPool pool;
otherwise you may get null pointer exception.
For more complex and performant solutions search 'efficient lazy singletor in java', which will most probably lead you to Enum
solution.