package com.hikktn.thread;import java.sql.*;import java.util.Map;import java.util.Properties;import java.util.Random;import java.util.concurrent.Executor;import java.util.concurrent.atomic.AtomicIntegerArray;/** * ThreadPoolTest * <p> * <p> * encoding:UTF-8 * * @author lisonglin 15:23 2022/4/4 */public class ThreadPoolTest { public static void main(String[] args) { ThreadPool threadPool = new ThreadPool(2); for (int i = 0; i < 5; i++) { new Thread(() -> { Connection connection = threadPool.getConnection(); try { Thread.sleep(new Random().nextInt(1000)); } catch (InterruptedException e) { e.printStackTrace(); } threadPool.releaseConnection(connection); }).start(); } }}class ThreadPool { /** * 线程池中线程的最大数量 */ private final int poolSize; /** * 连接对象数组 */ private Connection[] connections; /** * 连接状态数组 0 空闲 1 占用 */ private AtomicIntegerArray states; /** * 初始化线程池 * * @param poolSize */ public ThreadPool(int poolSize) { this.poolSize = poolSize; this.connections = new Connection[poolSize]; this.states = new AtomicIntegerArray(new int[poolSize]); for (int i = 0; i < poolSize; i++) { connections[i] = new MockConnection(Thread.currentThread().getName() + " connection:" + (i + 1)); } } /** * 获取连接 * */ public Connection getConnection() { while (true) { for (int i = 0; i < poolSize; i++) { if (states.get(i) == 0) { if (states.compareAndSet(i, 0, 1)) { System.out.println(Thread.currentThread().getName() + " get connection:" + connections[i]); return connections[i]; } } } synchronized (this) { try { System.out.println(Thread.currentThread().getName() + " wait for connection"); wait(); } catch (InterruptedException e) { e.printStackTrace(); } } } } /** * 释放连接 */ public void releaseConnection(Connection connection) { for (int i = 0; i < poolSize; i++) { if (connection == connections[i]) { if (states.compareAndSet(i, 1, 0)) { System.out.println(Thread.currentThread().getName() + " release connection:" + connection); synchronized (this) { notifyAll(); } break; } } } }}class MockConnection implements Connection { private final String name; public MockConnection(String name) { this.name = name; } @Override public String toString() { return "MockConnection{" + "name='" + name + '\'' + '}'; } @Override public Statement createStatement() throws SQLException { return null; } @Override public PreparedStatement prepareStatement(String sql) throws SQLException { return null; } @Override public CallableStatement prepareCall(String sql) throws SQLException { return null; } @Override public String nativeSQL(String sql) throws SQLException { return null; } @Override public void setAutoCommit(boolean autoCommit) throws SQLException { } @Override public boolean getAutoCommit() throws SQLException { return false; } @Override public void commit() throws SQLException { } @Override public void rollback() throws SQLException { } @Override public void close() throws SQLException { } @Override public boolean isClosed() throws SQLException { return false; } @Override public DatabaseMetaData getMetaData() throws SQLException { return null; } @Override public void setReadOnly(boolean readOnly) throws SQLException { } @Override public boolean isReadOnly() throws SQLException { return false; } @Override public void setCatalog(String catalog) throws SQLException { } @Override public String getCatalog() throws SQLException { return null; } @Override public void setTransactionIsolation(int level) throws SQLException { } @Override public int getTransactionIsolation() throws SQLException { return 0; } @Override public SQLWarning getWarnings() throws SQLException { return null; } @Override public void clearWarnings() throws SQLException { } @Override public Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException { return null; } @Override public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency) throws SQLException { return null; } @Override public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) throws SQLException { return null; } @Override public Map<String, Class<?>> getTypeMap() throws SQLException { return null; } @Override public void setTypeMap(Map<String, Class<?>> map) throws SQLException { } @Override public void setHoldability(int holdability) throws SQLException { } @Override public int getHoldability() throws SQLException { return 0; } @Override public Savepoint setSavepoint() throws SQLException { return null; } @Override public Savepoint setSavepoint(String name) throws SQLException { return null; } @Override public void rollback(Savepoint savepoint) throws SQLException { } @Override public void releaseSavepoint(Savepoint savepoint) throws SQLException { } @Override public Statement createStatement(int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException { return null; } @Override public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException { return null; } @Override public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException { return null; } @Override public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SQLException { return null; } @Override public PreparedStatement prepareStatement(String sql, int[] columnIndexes) throws SQLException { return null; } @Override public PreparedStatement prepareStatement(String sql, String[] columnNames) throws SQLException { return null; } @Override public Clob createClob() throws SQLException { return null; } @Override public Blob createBlob() throws SQLException { return null; } @Override public NClob createNClob() throws SQLException { return null; } @Override public SQLXML createSQLXML() throws SQLException { return null; } @Override public boolean isValid(int timeout) throws SQLException { return false; } @Override public void setClientInfo(String name, String value) throws SQLClientInfoException { } @Override public void setClientInfo(Properties properties) throws SQLClientInfoException { } @Override public String getClientInfo(String name) throws SQLException { return null; } @Override public Properties getClientInfo() throws SQLException { return null; } @Override public Array createArrayOf(String typeName, Object[] elements) throws SQLException { return null; } @Override public Struct createStruct(String typeName, Object[] attributes) throws SQLException { return null; } @Override public void setSchema(String schema) throws SQLException { } @Override public String getSchema() throws SQLException { return null; } @Override public void abort(Executor executor) throws SQLException { } @Override public void setNetworkTimeout(Executor executor, int milliseconds) throws SQLException { } @Override public int getNetworkTimeout() throws SQLException { return 0; } @Override public <T> T unwrap(Class<T> iface) throws SQLException { return null; } @Override public boolean isWrapperFor(Class<?> iface) throws SQLException { return false; }}
Thread-0 get connection:MockConnection{name='main connection:1'}Thread-2 wait for connectionThread-1 get connection:MockConnection{name='main connection:2'}Thread-3 wait for connectionThread-4 wait for connectionThread-1 release connection:MockConnection{name='main connection:2'}Thread-4 get connection:MockConnection{name='main connection:2'}Thread-3 wait for connectionThread-2 wait for connectionThread-0 release connection:MockConnection{name='main connection:1'}Thread-2 get connection:MockConnection{name='main connection:1'}Thread-3 wait for connectionThread-2 release connection:MockConnection{name='main connection:1'}Thread-3 get connection:MockConnection{name='main connection:1'}Thread-4 release connection:MockConnection{name='main connection:2'}Thread-3 release connection:MockConnection{name='main connection:1'}