From b0420db2db35e047a46b76ad2f0e8c2e21b5221a Mon Sep 17 00:00:00 2001
From: life <1733802689@qq.com>
Date: Sun, 29 Oct 2023 09:05:53 +0800
Subject: [PATCH] =?UTF-8?q?=E6=89=8B=E5=86=99redis=E7=BA=BF=E7=A8=8B?=
=?UTF-8?q?=E6=B1=A0=EF=BC=8Credis=E6=9C=AA=E5=90=AF=E5=8A=A8?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.gitignore | 38 ++++++
.idea/.gitignore | 8 ++
.idea/encodings.xml | 7 +
.idea/misc.xml | 14 ++
.idea/uiDesigner.xml | 124 ++++++++++++++++++
.idea/vcs.xml | 6 +
pom.xml | 52 ++++++++
.../java/com/lc/Runner/SpringJunitRunner.java | 54 ++++++++
.../java/com/lc/redisPool/IRedisPool.java | 29 ++++
.../java/com/lc/redisPool/MyRedisPool.java | 82 ++++++++++++
src/main/java/com/lc/test/RedisPoolTest.java | 58 ++++++++
src/main/resources/spring-servlet.xml | 6 +
12 files changed, 478 insertions(+)
create mode 100644 .gitignore
create mode 100644 .idea/.gitignore
create mode 100644 .idea/encodings.xml
create mode 100644 .idea/misc.xml
create mode 100644 .idea/uiDesigner.xml
create mode 100644 .idea/vcs.xml
create mode 100644 pom.xml
create mode 100644 src/main/java/com/lc/Runner/SpringJunitRunner.java
create mode 100644 src/main/java/com/lc/redisPool/IRedisPool.java
create mode 100644 src/main/java/com/lc/redisPool/MyRedisPool.java
create mode 100644 src/main/java/com/lc/test/RedisPoolTest.java
create mode 100644 src/main/resources/spring-servlet.xml
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..5ff6309
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,38 @@
+target/
+!.mvn/wrapper/maven-wrapper.jar
+!**/src/main/**/target/
+!**/src/test/**/target/
+
+### IntelliJ IDEA ###
+.idea/modules.xml
+.idea/jarRepositories.xml
+.idea/compiler.xml
+.idea/libraries/
+*.iws
+*.iml
+*.ipr
+
+### Eclipse ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+build/
+!**/src/main/**/build/
+!**/src/test/**/build/
+
+### VS Code ###
+.vscode/
+
+### Mac OS ###
+.DS_Store
\ No newline at end of file
diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 0000000..35410ca
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,8 @@
+# 默认忽略的文件
+/shelf/
+/workspace.xml
+# 基于编辑器的 HTTP 客户端请求
+/httpRequests/
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml
diff --git a/.idea/encodings.xml b/.idea/encodings.xml
new file mode 100644
index 0000000..aa00ffa
--- /dev/null
+++ b/.idea/encodings.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..82dbec8
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/uiDesigner.xml b/.idea/uiDesigner.xml
new file mode 100644
index 0000000..2b63946
--- /dev/null
+++ b/.idea/uiDesigner.xml
@@ -0,0 +1,124 @@
+
+
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+
+
+ -
+
+
+ -
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..94a25f7
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..c677e54
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,52 @@
+
+
+ 4.0.0
+
+ com.lc
+ RedisTest
+ 1.0-SNAPSHOT
+
+
+ 17
+ 17
+ UTF-8
+
+
+
+
+ org.springframework
+ spring-beans
+ 6.0.12
+
+
+ org.springframework
+ spring-context
+ 6.0.12
+
+
+ org.springframework
+ spring-core
+ 6.0.12
+
+
+
+ redis.clients
+ jedis
+ 2.7.2
+
+
+ junit
+ junit
+ 4.12
+ compile
+
+
+ maven_repository.org.springframework
+ spring-test
+ 6.0.6
+
+
+
+
diff --git a/src/main/java/com/lc/Runner/SpringJunitRunner.java b/src/main/java/com/lc/Runner/SpringJunitRunner.java
new file mode 100644
index 0000000..98f1471
--- /dev/null
+++ b/src/main/java/com/lc/Runner/SpringJunitRunner.java
@@ -0,0 +1,54 @@
+package com.lc.Runner;
+
+import org.junit.runner.Description;
+import org.junit.runner.Runner;
+import org.junit.runner.notification.Failure;
+import org.junit.runner.notification.RunNotifier;
+import redis.clients.jedis.JedisPool;
+import redis.clients.jedis.JedisPoolConfig;
+
+/**
+ * 测试用例
+ */
+public class SpringJunitRunner extends Runner {
+
+
+ private Class> testClass;
+ private JedisPool jedisPool;
+
+ public SpringJunitRunner(Class> testClass) {
+ this.testClass = testClass;
+ }
+
+
+ @Override
+ public Description getDescription() {
+ return Description.createTestDescription(testClass, "Redis Pool Test");
+ }
+
+ @Override
+ public void run(RunNotifier runNotifier) {
+ // 初始化Jedis连接池
+ JedisPoolConfig config = new JedisPoolConfig();
+ config.setMaxTotal(10);
+ config.setMaxIdle(5);
+ config.setMinIdle(1);
+ jedisPool = new JedisPool(config, "124.221.214.183", 6379);
+
+ // 运行测试用例
+ runNotifier.fireTestStarted(getDescription());
+ try {
+ testClass.newInstance();
+ } catch (InstantiationException | IllegalAccessException e) {
+ runNotifier.fireTestFailure(new Failure(getDescription(), e));
+ }
+ runNotifier.fireTestFinished(getDescription());
+
+ // 关闭Jedis连接池
+ jedisPool.destroy();
+ }
+
+ public JedisPool getJedisPool() {
+ return jedisPool;
+ }
+}
diff --git a/src/main/java/com/lc/redisPool/IRedisPool.java b/src/main/java/com/lc/redisPool/IRedisPool.java
new file mode 100644
index 0000000..6a4f4d6
--- /dev/null
+++ b/src/main/java/com/lc/redisPool/IRedisPool.java
@@ -0,0 +1,29 @@
+package com.lc.redisPool;
+
+import redis.clients.jedis.Jedis;
+
+/**
+ * 定义一个连接池的接口
+ */
+public interface IRedisPool {
+
+ /**
+ * 连接池初始化
+ * @param maxTotal 最大连接数
+ * @param maxWaiMillis 最长连接时间
+ */
+ public void init(int maxTotal,long maxWaiMillis);
+
+ /**
+ * 获取连接
+ * @return
+ * @throws Exception
+ */
+ public Jedis getResource() throws Exception;
+
+ /**
+ * 获取连接
+ * @param jedis
+ */
+ public void release(Jedis jedis);
+}
diff --git a/src/main/java/com/lc/redisPool/MyRedisPool.java b/src/main/java/com/lc/redisPool/MyRedisPool.java
new file mode 100644
index 0000000..5c8749f
--- /dev/null
+++ b/src/main/java/com/lc/redisPool/MyRedisPool.java
@@ -0,0 +1,82 @@
+package com.lc.redisPool;
+
+import redis.clients.jedis.Jedis;
+
+import java.util.Queue;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * redis连接池
+ */
+public class MyRedisPool implements IRedisPool{
+
+ private int maxTotal;
+ public long maxWaitMillis;
+ //定义一个空闲的连续集合
+ private LinkedBlockingQueue idleObjects=null;
+ //定义一个活动的连续集合
+ private LinkedBlockingQueue activeObjects=null;
+ //总的redis连接数量(int)原子操作粒
+ private AtomicInteger count =new AtomicInteger();
+ @Override
+ public void init(int maxTotal, long maxWaiMillis) {
+ this.maxTotal=maxTotal;
+ this.maxWaitMillis=maxWaiMillis;
+ idleObjects=new LinkedBlockingQueue(maxTotal);
+ activeObjects=new LinkedBlockingQueue(maxTotal);
+ }
+
+ @Override
+ public Jedis getResource() throws Exception {
+ //伪代码理思路
+ //记录开始时间戳,用于判断超时时间
+ long startTime = System.currentTimeMillis();
+ //从空闲连接集合中获取连接,如果获取到了一个空闲的连接,将该连接放入活动连接集合中,返回连接
+ Jedis redis = null;
+ while (redis == null) {
+ redis = idleObjects.poll();
+ if (redis != null) {
+ activeObjects.offer(redis);
+ return redis;
+ }
+ //如果无法拿到连接,判断连接是否已满
+ if (count.get() < maxTotal) {
+ if (count.incrementAndGet() <= maxTotal) {
+ redis = new Jedis("124.221.214.183", 6379);
+ System.out.println("---------Redis连接池创建了一个连接");
+ activeObjects.offer(redis);
+ return redis;
+ } else {
+ count.decrementAndGet();
+ }
+ }
+ try {
+ //如果连接满了,等待其他线程释放到空闲连接集合中,如果说一定的空闲时间,可以得到一个空闲连接,
+ //将连接放入到活动连接集合,返回该连接
+ redis = idleObjects.poll(maxWaitMillis - (System.currentTimeMillis() - startTime), TimeUnit.MILLISECONDS);
+ if (null!=redis){
+ activeObjects.offer(redis);
+ return redis;
+ }
+ }catch (Exception e){
+ e.printStackTrace();
+ }
+ //如果等待时间超过了我们最长的等待时间,抛出等待超时异常
+ if (maxWaitMillis < (System.currentTimeMillis() - startTime)){
+ throw new Exception("timeout,超过最长等待时间");
+ }else {
+ continue;
+ }
+ }
+ return redis;
+ }
+
+ @Override
+ public void release(Jedis jedis) {
+ if (activeObjects.remove(jedis)){
+ idleObjects.offer(jedis);
+ }
+ }
+}
diff --git a/src/main/java/com/lc/test/RedisPoolTest.java b/src/main/java/com/lc/test/RedisPoolTest.java
new file mode 100644
index 0000000..03b2101
--- /dev/null
+++ b/src/main/java/com/lc/test/RedisPoolTest.java
@@ -0,0 +1,58 @@
+package com.lc.test;
+
+
+import com.lc.Runner.SpringJunitRunner;
+import com.lc.redisPool.IRedisPool;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.test.context.ContextConfiguration;
+import redis.clients.jedis.Jedis;
+
+import java.util.concurrent.CountDownLatch;
+
+/**
+ *
+ */
+@RunWith(SpringJunitRunner.class)
+@ContextConfiguration(locations={"classpath:spring-servlet.xml"})
+public class RedisPoolTest {
+
+ @Autowired
+ private IRedisPool pool;
+ private final static int THREAD_NUM=10;
+ private final CountDownLatch cdl=new CountDownLatch(THREAD_NUM);//栅栏
+//发令枪 等待一定的时间点 栅栏 等待一定的数量
+
+ @Test
+ public void test() throws Exception {
+ //初始化连接池
+ pool.init(9,10000);
+ //模拟并发场景对Redis进行操作,分析连接池中是否只创建了指定的连接数
+
+ for (int i = 0; i < THREAD_NUM; i++) {
+ new Thread(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ cdl.await();//等待 等待一个唤醒指令,所有等待的线程同时执行
+ } catch (InterruptedException e) {
+ throw new RuntimeException(e);
+ }
+ Jedis jedis=null;
+ try {
+ jedis=pool.getResource();
+ jedis.incr("poolTest.incr");
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }finally {
+ pool.release(jedis);
+ }
+
+ }
+ }).start();
+ cdl.countDown();//计数 当等于0时唤醒所有的等待线程
+ }
+ Thread.sleep(2000);
+ }
+}
diff --git a/src/main/resources/spring-servlet.xml b/src/main/resources/spring-servlet.xml
new file mode 100644
index 0000000..6cf3ef5
--- /dev/null
+++ b/src/main/resources/spring-servlet.xml
@@ -0,0 +1,6 @@
+
+
+
+