1. 程式人生 > >java操作redis(三):實現一個redis連線池並附測試

java操作redis(三):實現一個redis連線池並附測試

環境:jdk1.7    redis3.2.8

所需jar包:jedis-2.9.0.jar     commons-pool2-2.3

Jedis連線池使用步驟如下:
1->獲取Jedis例項需要從JedisPool中獲取;
2->用完Jedis例項需要返還給JedisPool;
3->如果Jedis在使用過程中出錯,則也需要還給JedisPool;

=================連線池引數配置檔案redis.properties================

#*****************jedis連線引數設定*********************
#redis伺服器ip
redis.ip=169.254.130.122
#redis伺服器埠號
redis.port=6379
#redis訪問密碼
redis.passWord=test123
#與伺服器建立連線的超時時間
redis.timeout=3000
#************************jedis池引數設定*******************
#jedis的最大活躍連線數
jedis.pool.maxActive=100
#jedis最大空閒連線數
jedis.pool.maxIdle=50
#jedis池沒有連線物件返回時,等待可用連線的最大時間,單位毫秒,預設值為-1,表示永不超時。
#如果超過等待時間,則直接丟擲JedisConnectionException
jedis.pool.maxWait=1500
#從池中獲取連線的時候,是否進行有效檢查
jedis.pool.testOnBorrow=true
#歸還連線的時候,是否進行有效檢查
jedis.pool.testOnReturn=true
=================Redis連線池工具類RedisPoolUtil================
package com.wx.utils;

import java.util.Properties;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

/**
 * Redis連線池工具類
 */
public class RedisPoolUtil {
	private static JedisPool jedisPool = null;
	private static String redisConfigFile = "redis.properties";
	//把redis連線物件放到本地執行緒中
	private static ThreadLocal<Jedis> local=new ThreadLocal<Jedis>();
	
	//不允許通過new建立該類的例項
	private RedisPoolUtil() {
	}

	/**
	 * 初始化Redis連線池
	 */
	public static void initialPool() {
		try {
			Properties props = new Properties();
			//載入連線池配置檔案
			props.load(RedisPoolUtil.class.getClassLoader().getResourceAsStream(redisConfigFile));
			// 建立jedis池配置例項
			JedisPoolConfig config = new JedisPoolConfig();
			// 設定池配置項值
			config.setMaxTotal(Integer.valueOf(props.getProperty("jedis.pool.maxActive")));
			config.setMaxIdle(Integer.valueOf(props.getProperty("jedis.pool.maxIdle")));
			config.setMaxWaitMillis(Long.valueOf(props.getProperty("jedis.pool.maxWait")));
			config.setTestOnBorrow(Boolean.valueOf(props.getProperty("jedis.pool.testOnBorrow")));
			config.setTestOnReturn(Boolean.valueOf(props.getProperty("jedis.pool.testOnReturn")));
			// 根據配置例項化jedis池
			jedisPool = new JedisPool(config, props.getProperty("redis.ip"),
					Integer.valueOf(props.getProperty("redis.port")),
					Integer.valueOf(props.getProperty("redis.timeout")),
					props.getProperty("redis.passWord"));
			System.out.println("執行緒池被成功初始化");
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * 獲得連線
	 * @return Jedis
	 */
	public static Jedis getConn() { 
		//Redis物件
        Jedis jedis =local.get();
        if(jedis==null){
        	if (jedisPool == null) {    
            	initialPool();  
            }
        	jedis = jedisPool.getResource();
        	local.set(jedis);
        }
        return jedis;  
    }
	
	//新版本用close歸還連線
	public static void closeConn(){
		//從本地執行緒中獲取
		Jedis jedis =local.get();
		if(jedis!=null){
			jedis.close();
		}
		local.set(null);
	}
	
	//關閉池
	public static void closePool(){
		if(jedisPool!=null){
			jedisPool.close();
		}
	}
}

============執行緒測試類============
package com.wx.test;

import java.text.SimpleDateFormat;
import java.util.Date;
import com.wx.utils.RedisPoolUtil;
import redis.clients.jedis.Jedis;

public class TestPool {
	public static void main(String[] args) {
		//初始化連線池
		RedisPoolUtil.initialPool();
		//啟動1000個執行緒
		for (int i = 0; i < 1000; i++) {            
	        ClientThread t = new ClientThread(i);  
	        t.start();  
	    }
	}  
}
//執行緒類
class ClientThread extends Thread {  
    int i = 0;  
    public ClientThread(int i) {  
        this.i = i;  
    }  
    public void run() {  
    	Jedis jedis=RedisPoolUtil.getConn();
        Date date = new Date();  
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSS");  
        String time = sdf.format(date);  
        jedis.set("key"+i, time); 
        try {
        	//每次睡眠一個隨機時間
			Thread.sleep((int)(Math.random()*5000));
			String foo = jedis.get("key"+i);        
	        System.out.println("【輸出>>>>】key:" + foo + " 第:"+i+"個執行緒");
		} catch (InterruptedException e) {
			e.printStackTrace();
		}finally {
			RedisPoolUtil.closeConn();
		}
    }  
}  
執行過程中,去伺服器看連線數
127.0.0.1:6379> info clients
# Clients
connected_clients:102
client_longest_output_list:0
client_biggest_input_buf:0
blocked_clients:0
127.0.0.1:6379> info clients
# Clients
connected_clients:70
client_longest_output_list:0
client_biggest_input_buf:0
blocked_clients:0
127.0.0.1:6379> info clients
# Clients
connected_clients:53
client_longest_output_list:0
client_biggest_input_buf:0
blocked_clients:0
127.0.0.1:6379> info clients
# Clients
connected_clients:2
client_longest_output_list:0
client_biggest_input_buf:0
blocked_clients:0
127.0.0.1:6379> info clients
# Clients
connected_clients:2
client_longest_output_list:0
client_biggest_input_buf:0
blocked_clients:0
127.0.0.1:6379> 
可以看出連線池中最大100個活躍連線迅速被佔滿,(最開始102個是因為我單獨啟動了兩個連線)

然後連線用完了,迅速歸還連線

java端的執行結果


可以看出有超時沒拿到連線的報錯!

ok,測試成功!