1. import java.sql.*;
    2. import java.util.Map;
    3. import java.util.Properties;
    4. import java.util.concurrent.Executor;
    5. import java.util.concurrent.atomic.AtomicIntegerArray;
    6. public class TestPool {
    7. public static void main(String[] args) throws InterruptedException {
    8. Pool pool = new Pool(2);
    9. for (int i = 0; i <5 ; i++) {
    10. new Thread(()->{
    11. //借连接
    12. Connection connection = pool.borrow();
    13. try {
    14. //模拟连接使用
    15. Thread.sleep(1000);
    16. } catch (InterruptedException e) {
    17. e.printStackTrace();
    18. }
    19. pool.free(connection);
    20. }).start();
    21. }
    22. }
    23. }
    24. class Pool{
    25. //1.连接池大小
    26. private final int poolSize;
    27. //2.连接数组
    28. private Connection[] connections;
    29. //3.连接状态数组:0表示空闲,1表示繁忙,这里用原子数组修饰,使得对其操作均是原子,保证线程安全,不需要在方法里手动实现线程安全
    30. private AtomicIntegerArray states;
    31. //4.构造方法
    32. public Pool(int poolSize) {
    33. this.poolSize = poolSize;
    34. //poolSize确定,连接数组以及状态数组则确定
    35. this.connections = new Connection[poolSize];
    36. this.states = new AtomicIntegerArray(new int[poolSize]);
    37. //初始化数组
    38. for (int i=0;i<poolSize;i++){
    39. connections[i] = new MockConnection();
    40. }
    41. }
    42. //5.借出连接
    43. public Connection borrow() throws InterruptedException {
    44. while (true){
    45. for (int i=0;i<poolSize;i++){
    46. //获取空闲连接
    47. if(states.get(i)==0){
    48. if (states.compareAndSet(i,0,1)) {
    49. return connections[i];
    50. }
    51. }
    52. }
    53. //如果没有空闲连接,调用该方法的当前线程进入等待状态
    54. synchronized (this){
    55. this.wait();
    56. }
    57. }
    58. }
    59. //6.归还连接
    60. public void free(Connection conn){
    61. for (int i = 0; i <poolSize ; i++) {
    62. //找到需要归还的连接
    63. if(connections[i]==conn){
    64. //注意归还线程的情况下,该连接一定被当前线程持有,不会发生线程竞争,直接set规划即可
    65. states.set(i,0);
    66. synchronized (this){
    67. this.notifyAll();//唤醒在当前对象上等待的所有线程
    68. }
    69. break;
    70. }
    71. }
    72. }
    73. }
    74. class MockConnection implements Connection{
    75. public MockConnection() {
    76. super();
    77. }
    78. @Override functions..
    79. }

    几个实现细节需要注意:

    • 连接状态的判断是通过一个状态数组实现的,数组中存储0-1,表示链接空闲or不可用
    • 用Atomatic修饰数组,是要保证对数组的操作均是原子性操作,但不能保证线程安全,原子和线程安全是两码事。
    • borrow()方法要while循环,为了能取到一份Connection对象,而如果一次for循环仍取不到,则要进入wait等待状态
    • borrow()方法中的CAS操作,是解决多线程多次获取同一Connection对象问题,当某一线程的CAS操作无法执行,那么就获取不到该Connection对象。
    • borrow()方法中的CAS实际上即实现对连接数组中每个元素的并发操作,无锁实现。