1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
| package pool;
import java.lang.reflect.Proxy;
import java.sql.Connection;
import java.sql.DriverManager;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.TimeUnit;
public class MyConnectionPool {
private final String jdbcUrl;
private final String username;
private final String password;
private final int maxPoolSize;
private final int initPoolSize;
private final long waitTimeout;
private final BlockingQueue<Connection> pool;
public MyConnectionPool(String jdbcUrl, String username, String password,
int initPoolSize, int maxPoolSize, long waitTimeout) throws Exception {
this.jdbcUrl = jdbcUrl;
this.username = username;
this.password = password;
this.initPoolSize = initPoolSize;
this.maxPoolSize = maxPoolSize;
this.waitTimeout = waitTimeout;
this.pool = new ArrayBlockingQueue<>(maxPoolSize);
init();
}
private void init() throws Exception {
for (int i = 0; i < initPoolSize; i++) {
pool.offer(createRealConnection());
}
System.out.println("Connection pool initialized, size=" + initPoolSize);
}
/** 创建真实 JDBC 连接 */
private Connection createRealConnection() throws Exception {
return DriverManager.getConnection(jdbcUrl, username, password);
}
/** 获取连接(可能需要等待) */
public Connection getConnection() throws Exception {
Connection conn = pool.poll();
if (conn != null) {
return wrap(conn);
}
synchronized (pool) {
if (pool.size() < maxPoolSize) {
return wrap(createRealConnection());
}
}
conn = pool.poll(waitTimeout, TimeUnit.MILLISECONDS);
if (conn == null) {
throw new RuntimeException("Timeout: failed to get DB connection");
}
return wrap(conn);
}
/** 包装 connection,拦截 close() 并归还到 pool */
private Connection wrap(Connection realConnection) {
return (Connection) Proxy.newProxyInstance(
realConnection.getClass().getClassLoader(),
new Class[]{Connection.class},
(proxy, method, args) -> {
if ("close".equals(method.getName())) {
pool.offer(realConnection);
return null;
}
return method.invoke(realConnection, args);
}
);
}
}
|