1. package com.hikktn.thread;
    2. import java.sql.*;
    3. import java.util.Map;
    4. import java.util.Properties;
    5. import java.util.Random;
    6. import java.util.concurrent.Executor;
    7. import java.util.concurrent.atomic.AtomicIntegerArray;
    8. /**
    9. * ThreadPoolTest
    10. * <p>
    11. * <p>
    12. * encoding:UTF-8
    13. *
    14. * @author lisonglin 15:23 2022/4/4
    15. */
    16. public class ThreadPoolTest {
    17. public static void main(String[] args) {
    18. ThreadPool threadPool = new ThreadPool(2);
    19. for (int i = 0; i < 5; i++) {
    20. new Thread(() -> {
    21. Connection connection = threadPool.getConnection();
    22. try {
    23. Thread.sleep(new Random().nextInt(1000));
    24. } catch (InterruptedException e) {
    25. e.printStackTrace();
    26. }
    27. threadPool.releaseConnection(connection);
    28. }).start();
    29. }
    30. }
    31. }
    32. class ThreadPool {
    33. /**
    34. * 线程池中线程的最大数量
    35. */
    36. private final int poolSize;
    37. /**
    38. * 连接对象数组
    39. */
    40. private Connection[] connections;
    41. /**
    42. * 连接状态数组 0 空闲 1 占用
    43. */
    44. private AtomicIntegerArray states;
    45. /**
    46. * 初始化线程池
    47. *
    48. * @param poolSize
    49. */
    50. public ThreadPool(int poolSize) {
    51. this.poolSize = poolSize;
    52. this.connections = new Connection[poolSize];
    53. this.states = new AtomicIntegerArray(new int[poolSize]);
    54. for (int i = 0; i < poolSize; i++) {
    55. connections[i] = new MockConnection(Thread.currentThread().getName() + " connection:" + (i + 1));
    56. }
    57. }
    58. /**
    59. * 获取连接
    60. *
    61. */
    62. public Connection getConnection() {
    63. while (true) {
    64. for (int i = 0; i < poolSize; i++) {
    65. if (states.get(i) == 0) {
    66. if (states.compareAndSet(i, 0, 1)) {
    67. System.out.println(Thread.currentThread().getName() + " get connection:" + connections[i]);
    68. return connections[i];
    69. }
    70. }
    71. }
    72. synchronized (this) {
    73. try {
    74. System.out.println(Thread.currentThread().getName() + " wait for connection");
    75. wait();
    76. } catch (InterruptedException e) {
    77. e.printStackTrace();
    78. }
    79. }
    80. }
    81. }
    82. /**
    83. * 释放连接
    84. */
    85. public void releaseConnection(Connection connection) {
    86. for (int i = 0; i < poolSize; i++) {
    87. if (connection == connections[i]) {
    88. if (states.compareAndSet(i, 1, 0)) {
    89. System.out.println(Thread.currentThread().getName() + " release connection:" + connection);
    90. synchronized (this) {
    91. notifyAll();
    92. }
    93. break;
    94. }
    95. }
    96. }
    97. }
    98. }
    99. class MockConnection implements Connection {
    100. private final String name;
    101. public MockConnection(String name) {
    102. this.name = name;
    103. }
    104. @Override
    105. public String toString() {
    106. return "MockConnection{" +
    107. "name='" + name + '\'' +
    108. '}';
    109. }
    110. @Override
    111. public Statement createStatement() throws SQLException {
    112. return null;
    113. }
    114. @Override
    115. public PreparedStatement prepareStatement(String sql) throws SQLException {
    116. return null;
    117. }
    118. @Override
    119. public CallableStatement prepareCall(String sql) throws SQLException {
    120. return null;
    121. }
    122. @Override
    123. public String nativeSQL(String sql) throws SQLException {
    124. return null;
    125. }
    126. @Override
    127. public void setAutoCommit(boolean autoCommit) throws SQLException {
    128. }
    129. @Override
    130. public boolean getAutoCommit() throws SQLException {
    131. return false;
    132. }
    133. @Override
    134. public void commit() throws SQLException {
    135. }
    136. @Override
    137. public void rollback() throws SQLException {
    138. }
    139. @Override
    140. public void close() throws SQLException {
    141. }
    142. @Override
    143. public boolean isClosed() throws SQLException {
    144. return false;
    145. }
    146. @Override
    147. public DatabaseMetaData getMetaData() throws SQLException {
    148. return null;
    149. }
    150. @Override
    151. public void setReadOnly(boolean readOnly) throws SQLException {
    152. }
    153. @Override
    154. public boolean isReadOnly() throws SQLException {
    155. return false;
    156. }
    157. @Override
    158. public void setCatalog(String catalog) throws SQLException {
    159. }
    160. @Override
    161. public String getCatalog() throws SQLException {
    162. return null;
    163. }
    164. @Override
    165. public void setTransactionIsolation(int level) throws SQLException {
    166. }
    167. @Override
    168. public int getTransactionIsolation() throws SQLException {
    169. return 0;
    170. }
    171. @Override
    172. public SQLWarning getWarnings() throws SQLException {
    173. return null;
    174. }
    175. @Override
    176. public void clearWarnings() throws SQLException {
    177. }
    178. @Override
    179. public Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException {
    180. return null;
    181. }
    182. @Override
    183. public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency) throws SQLException {
    184. return null;
    185. }
    186. @Override
    187. public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) throws SQLException {
    188. return null;
    189. }
    190. @Override
    191. public Map<String, Class<?>> getTypeMap() throws SQLException {
    192. return null;
    193. }
    194. @Override
    195. public void setTypeMap(Map<String, Class<?>> map) throws SQLException {
    196. }
    197. @Override
    198. public void setHoldability(int holdability) throws SQLException {
    199. }
    200. @Override
    201. public int getHoldability() throws SQLException {
    202. return 0;
    203. }
    204. @Override
    205. public Savepoint setSavepoint() throws SQLException {
    206. return null;
    207. }
    208. @Override
    209. public Savepoint setSavepoint(String name) throws SQLException {
    210. return null;
    211. }
    212. @Override
    213. public void rollback(Savepoint savepoint) throws SQLException {
    214. }
    215. @Override
    216. public void releaseSavepoint(Savepoint savepoint) throws SQLException {
    217. }
    218. @Override
    219. public Statement createStatement(int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException {
    220. return null;
    221. }
    222. @Override
    223. public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException {
    224. return null;
    225. }
    226. @Override
    227. public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException {
    228. return null;
    229. }
    230. @Override
    231. public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SQLException {
    232. return null;
    233. }
    234. @Override
    235. public PreparedStatement prepareStatement(String sql, int[] columnIndexes) throws SQLException {
    236. return null;
    237. }
    238. @Override
    239. public PreparedStatement prepareStatement(String sql, String[] columnNames) throws SQLException {
    240. return null;
    241. }
    242. @Override
    243. public Clob createClob() throws SQLException {
    244. return null;
    245. }
    246. @Override
    247. public Blob createBlob() throws SQLException {
    248. return null;
    249. }
    250. @Override
    251. public NClob createNClob() throws SQLException {
    252. return null;
    253. }
    254. @Override
    255. public SQLXML createSQLXML() throws SQLException {
    256. return null;
    257. }
    258. @Override
    259. public boolean isValid(int timeout) throws SQLException {
    260. return false;
    261. }
    262. @Override
    263. public void setClientInfo(String name, String value) throws SQLClientInfoException {
    264. }
    265. @Override
    266. public void setClientInfo(Properties properties) throws SQLClientInfoException {
    267. }
    268. @Override
    269. public String getClientInfo(String name) throws SQLException {
    270. return null;
    271. }
    272. @Override
    273. public Properties getClientInfo() throws SQLException {
    274. return null;
    275. }
    276. @Override
    277. public Array createArrayOf(String typeName, Object[] elements) throws SQLException {
    278. return null;
    279. }
    280. @Override
    281. public Struct createStruct(String typeName, Object[] attributes) throws SQLException {
    282. return null;
    283. }
    284. @Override
    285. public void setSchema(String schema) throws SQLException {
    286. }
    287. @Override
    288. public String getSchema() throws SQLException {
    289. return null;
    290. }
    291. @Override
    292. public void abort(Executor executor) throws SQLException {
    293. }
    294. @Override
    295. public void setNetworkTimeout(Executor executor, int milliseconds) throws SQLException {
    296. }
    297. @Override
    298. public int getNetworkTimeout() throws SQLException {
    299. return 0;
    300. }
    301. @Override
    302. public <T> T unwrap(Class<T> iface) throws SQLException {
    303. return null;
    304. }
    305. @Override
    306. public boolean isWrapperFor(Class<?> iface) throws SQLException {
    307. return false;
    308. }
    309. }
    1. Thread-0 get connection:MockConnection{name='main connection:1'}
    2. Thread-2 wait for connection
    3. Thread-1 get connection:MockConnection{name='main connection:2'}
    4. Thread-3 wait for connection
    5. Thread-4 wait for connection
    6. Thread-1 release connection:MockConnection{name='main connection:2'}
    7. Thread-4 get connection:MockConnection{name='main connection:2'}
    8. Thread-3 wait for connection
    9. Thread-2 wait for connection
    10. Thread-0 release connection:MockConnection{name='main connection:1'}
    11. Thread-2 get connection:MockConnection{name='main connection:1'}
    12. Thread-3 wait for connection
    13. Thread-2 release connection:MockConnection{name='main connection:1'}
    14. Thread-3 get connection:MockConnection{name='main connection:1'}
    15. Thread-4 release connection:MockConnection{name='main connection:2'}
    16. Thread-3 release connection:MockConnection{name='main connection:1'}