大家好,又见面了,我是你们的朋友全栈君。
报错信息:Exception in thread “main” redis.clients.jedis.exceptions.JedisExhaustedPoolException: Could not get a resource since the pool is exhausted
在网上找了很久没有找到,现在看来提示已经讲的很明白了,Jedis池耗尽异常:由于池已耗尽,无法获取资源
原因就是最大连接数不够使用,我在类中启动了60个并发线程,然而连接池最大连接数只有50,所以报错。
代码语言:javascript复制package com.wang.distributedlock.utils;
import org.springframework.beans.factory.annotation.Value;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
/**
* @author wzq
* @date 2020/05/29/11:09
*/
public class JedisPoolUtil {
@Value("${redis.host}")
private static final String HOST = "127.0.0.1";
@Value("${redis.port}")
private static final int PORT = 6379;
@Value("${redis.password}")
private static final String PASSWORD = "123456";
private static volatile JedisPool jedisPool = null;
public static JedisPool getJedisPoolInstance() {
if (jedisPool == null) {
JedisPoolConfig poolConfig = new JedisPoolConfig();
// 最大连接数
poolConfig.setMaxTotal(50);
// 最大空闲连接数
poolConfig.setMaxIdle(30);
poolConfig.setMinIdle(10);
// 最大等待时间
poolConfig.setMaxWaitMillis(20 * 1000);
// 检查连接可用性, 确保获取的redis实例可用
// 在borrow一个jedis实例时,是否提前进行validate操作;如果为true,则得到的jedis实例均是可用的
poolConfig.setTestOnBorrow(false);
poolConfig.setTestOnCreate(false);
// 无密码构造
//jedisPool = new JedisPool(poolConfig, HOST, PORT);
// 有密码构造,需要设置密码,设置密码可以在获取到jedis对象后,jedis.auth("密码"),也可以在此时使用构造入参设置
jedisPool = new JedisPool(poolConfig, HOST, PORT, 10 * 1000, PASSWORD);
}
return jedisPool;
}
public static Jedis getJedisInstance() {
Jedis jedis = getJedisPoolInstance().getResource();
//jedis.auth("123456");
return jedis;
}
public static void release(Jedis jedis) {
jedis.close();
}
}
引用的类中
代码语言:javascript复制package com.wang.distributedlock.zk;
import com.wang.distributedlock.utils.JedisPoolUtil;
import com.wang.distributedlock.utils.RedisTool;
import redis.clients.jedis.Jedis;
import java.util.UUID;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* @author wzq
* date: 2019/12/23 11:28
* description:
*/
public class OrderService implements Runnable {
private static CyclicBarrier cb = new CyclicBarrier(60);
// 订单号生成类
// 将orderNumGenerator或者count任意一处加上static,getNumber()加上同步锁,依然是线程安全的,因为使用的是同一个generator,而且加了锁是线程安全的
// 效果等同于静态锁,很多OrderService实例共用一把锁
private OrderNumGenerator orderNumGenerator = new OrderNumGenerator();
// 实现方式1
//private DistributeLock lock = new ZookeeperDistributeLock();
// 实现方式2
//private DistributeLock lock = new ZookeeperDistributeLock2();
/**
* 这么多OrderService实例共用一把锁,可以保证线程安全,但在集群部署多机模式下,
* 即便每台机器一次有一个请求获得锁,机器足够多依然会导致并发问题
*/
private static Lock rtLock = new ReentrantLock();
//实现方式3,redis分布式锁
//private Jedis jedis = RedisTool.getJedis();
private Jedis jedis = JedisPoolUtil.getJedisInstance();
public void run() {
try {
cb.await();
} catch (InterruptedException | BrokenBarrierException e) {
e.printStackTrace();
}
getNumber();
}
public void getNumber() {
String requestId = UUID.randomUUID().toString();
try {
//lock.getLock();
//rtLock.lock();
// Redis服务端单机部署,需要回调
// redis锁使用此段生成订单代码
/*if (RedisTool.tryGetDistributedLock(jedis, "lock", requestId, 2000)) {
String number = orderNumGenerator.getNumber();
System.out.println(Thread.currentThread().getName() "-" System.currentTimeMillis() ",产生了订单:" number);
} else {
this.getNumber();
}*/
// zookeeper锁或者不加锁使用此段生成代码订单
String number = orderNumGenerator.getNumber();
System.out.println(Thread.currentThread().getName() "-" System.currentTimeMillis() ",产生了订单:" number);
} catch (Exception e) {
e.printStackTrace();
} finally {
//lock.unlock();
//rtLock.unlock();
//Redis服务端单机部署,需要回调
//RedisTool.releaseDistributedLock(jedis, "lock", requestId);
}
}
public static void main(String[] args) {
System.out.println("####生成了订单####");
for (int i = 0; i < 60; i ) {
new Thread(new OrderService()).start();
}
}
}
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。