我自己编写了一个redis的客户端,在测并发的时候发现获取到的redis连接无法归还到连接池
这是单元测试类
public class RedisTest {
private static final ExecutorService executorService = Executors.newFixedThreadPool(1000);
private static CyclicBarrier c = new CyclicBarrier(200);
@Test
public void simpleTest() {
System.out.println(RedisUtil.get("yany_test"));
}
@Test
public void test() throws Exception {
for (int i = 0; i < 300; i++) {
executorService.submit(() -> {
// try {
// c.await();
// } catch (Exception e) {
// e.printStackTrace();
// }
System.out.println("num end end====" + c.getNumberWaiting() + " " + Thread.currentThread().getId() + " " + Thread.currentThread().getName());
System.out.println("id =====>:" + Thread.currentThread().getId() + " " + Thread.currentThread().getName() + " " + RedisUtil.get("yany_test"));
});
}
Thread.sleep(200000);
}
}
基本配置
jedis.pool.maxActive=20
jedis.pool.maxIdle=5
jedis.pool.maxWait=100
连接的工厂类
public class RedisFactory {
private static JedisPool jedisPool = null;
//把redis连接对象放到本地线程中
static {
try {
Properties props = new Properties();
//加载连接池配置文件
props.load(RedisFactory.class.getClassLoader().getResourceAsStream("redis-config.properties"));
// 创建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"));
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 获得连接
*
* @return Jedis
*/
public static Jedis getConn() {
//Redis对象
return jedisPool.getResource();
}
//新版本用close归还连接
public static void closeConn(Jedis jedis) {
if (jedis != null) {
jedis.close();
}
}
//关闭池
public static void closePool() {
if (jedisPool != null) {
jedisPool.close();
}
}
public static JedisPool getJedisPool() {
return jedisPool;
}
}
封装的操作类
public class RedisUtil {
public static String get(String key) {
Jedis jedis = null;
try {
jedis = RedisFactory.getConn();
return jedis.get(key);
} finally {
RedisFactory.closeConn(jedis);
}
}
}
这是输出结果: 并发之后只有20个线程能读出来,其他线程一直在等待,也不报超时
理论上不应该,所有线程都能读出来吗?当一个线程执行完之后,会返回连接,问什么出现连接不够的现象?
按照题主的代码执行了一下,都能读到值,看题中的图片,线程265也已经读到了值,不知道题主是怎么判断
只有20个线程能读出来
的,另外所有线程都会阻塞,这是因为你使用了FixedThreadPool
,然而却没有显示的去关闭它,FixedThreadPool
的核心线程没有超时策略,所以并不会自动关闭。当他执行完一个任务后会阻塞等待下一个任务,如果没有下一个任务,他会一直阻塞。这就是为什么其他线程一直在等待,也不报超时
的原因。题主可以换一个线程池或者手动显示的去关闭它(所有线程执行完成后调用shutdown
方法)。