1, using the wait / notification connector taken to implement timeouts
Package cn.enjoyedu.ch1.pool; Import the java.sql.Connection; Import java.util.LinkedList; ** / * Class Description: implement connection pool * / public class the DBPool { / * a container for storing connection * / Private static the LinkedList <connection> the pool = new new the LinkedList <connection> (); / * limits connection pool size * / public the DBPool ( int initialSize) { IF (initialSize> 0 ) { for ( int I = 0; I <initialSize; ++ I ) { // analog connections take pool.addLast (SqlConnectImpl.fetchConnection ()); } } } / * release the connection, notifies the other thread wait for a connection * / public void the releaseConnection (Connection Connection) { IF (Connection =! null ) { the synchronized (the pool) { the pool .addLast (connection); // notify other threads wait for a connection pool.notifyAll (); } } } / * Get * / // can not be acquired in connection mills, lS will return null public connection fetchConnection ( Long Mills)throws InterruptedException { synchronized (pool){ //永不超时 if(mills<=0){ while(pool.isEmpty()){ pool.wait(); } return pool.removeFirst(); }else{ /*超时时刻*/ long future = System.currentTimeMillis()+mills; /*等待时长*/ long remaining = mills; while(pool.isEmpty()&&remaining>0){ pool.wait (Remaining); / * wake-up time, duration is recalculated wait * / Remaining = future- System.currentTimeMillis (); } Connection Connection = null ; IF (! pool.isEmpty ()) { Connection = pool.removeFirst ( ); } return Connection; } } } }
test
Package com.pool; Import the java.sql.Connection; Import java.util.concurrent.CountDownLatch; Import java.util.concurrent.atomic.AtomicInteger; / ** * Class Description: Test 1000 from the pool to take concurrent connections * / public class DBPoolTest { static DBPool the pool = new new DBPool (10 ); // controller: control main thread will wait for the end of all Woker before proceeding to the static CountDownLatch end; public static void main (String [] args) throws Exception { // The number of threads int threadCount = 50 ; End= New new a CountDownLatch (threadCount); int COUNT = 20 is; // number of operations of each thread of AtomicInteger GOT = new new of AtomicInteger (); // counter: Statistics can get connected to the thread of AtomicInteger notGot = new new of AtomicInteger (); // counter : statistics not get thread connection for ( int I = 0; I <threadCount; I ++ ) { the thread thread = new new the thread ( new new the worker (COUNT, gOT, notGot), "worker _" + I); Thread.start () ; } end.await (); //main thread here waiting System.out.println ( "Total tried:" + (threadCount * COUNT)); System.out.println ( "get the number of connections:" + GOT); System.out.println ( "number of failed connections:" + notGot); } static class the Worker the implements the Runnable { int COUNT; of AtomicInteger GOT; of AtomicInteger notGot; public the Worker ( int COUNT, of AtomicInteger GOT, of AtomicInteger notGot) { the this .count = COUNT; the this .got = GOT; the this .notGot = notGot; } public void RUN () { the while (COUNT> 0 ) { the try { // obtain a connection from the thread pool, you can not take into 1000ms, will return null // respectively counting the number of connections to obtain and got the number is not acquired notGot Connection Connection = pool.fetchConnection (1000 ); IF (Connection =! null ) { the try { Connection.createStatement (); Connection.commit (); }finally { pool.releaseConnection(connection); got.incrementAndGet(); } } else { notGot.incrementAndGet(); System.out.println(Thread.currentThread().getName() +"等待超时!"); } } catch (Exception ex) { } finally { count--; } } end.countDown(); } } }
result
2, implemented using a database connection pool semaphores
Package com.semaphore; Import the java.sql.Connection; Import java.util.LinkedList; Import java.util.concurrent.Semaphore; / ** * Class Description: Semaphore implement database connection pool * / public class DBPoolSemaphore { Private Final static int = 10 pool_size ; // two indicators, respectively, as well as the available pool and are connected to connection Private Final Semaphore Useful, Useless; // storage container database connection Private static the LinkedList <connection> the pool = new new the LinkedList <connection> ( ); // initialize the pool static { for (int i = 0; i < POOL_SIZE; i++) { pool.addLast(SqlConnectImpl.fetchConnection()); } } public DBPoolSemaphore() { this.useful = new Semaphore(10); this.useless = new Semaphore(0); } /*归还连接*/ public void returnConnect(Connection connection) throws InterruptedException { if(connection!=null) { System.out.println("Currently" + useful.getQueueLength () + "threads waiting for database connections !!" + "number of available connections:" + useful.availablePermits ()); useless.acquire (); the synchronized (the pool) { pool.addLast ( connection); } useful.release (); } } / * from the pool to get connected to * / public connection takeConnect () throws InterruptedException { useful.acquire (); connection connection; the synchronized (the pool) { connection = pool.removeFirst (); } useless.release (); return connection; } }
test
Package com.semaphore; Import the java.sql.Connection; Import java.util.Random; / ** * Class Description: Test database connection pool * / public class the AppTest { Private static DBPoolSemaphore DBPool = new new DBPoolSemaphore (); Private static class BusiThread the extends the thread { @Override public void RUN () { the Random R & lt = new new the Random (); // make each thread holding time is not the same connection Long Start = System.currentTimeMillis (); the try{ Connection Connect = dbPool.takeConnect (); System.out.println ( "the Thread _" + . Thread.currentThread () getId () + "_ [Total time database connection" + (System.currentTimeMillis () - start ) + "] MS." ); SleepTools.ms ( 100 + r.nextInt (100)); // simulate business operations, thread holds the query data connection System.out.println ( "query data is complete, return connection!" ) ; dbPool.returnConnect (Connect); } the catch (InterruptedException E) { } } } public static void main (String [] args) { for (int i = 0; i < 50; i++) { Thread thread = new BusiThread(); thread.start(); } } }
result
package com.semaphore; import java.sql.Connection; import java.util.LinkedList; import java.util.Random; import java.util.concurrent.Semaphore; /** *类说明:Semaphore实现数据库连接池 */ public class DBPoolNoUseless { private final static int POOL_SIZE = 10; private final Semaphore useful; //存放数据库连接的容器 private static LinkedList<Connection> pool = new LinkedList<Connection>(); //初始化池 static { for (int i = 0; i < POOL_SIZE; i++) { pool.addLast(SqlConnectImpl.fetchConnection()); } } public DBPoolNoUseless() { this.useful = new Semaphore(10); } /*归还连接*/ public void returnConnect(Connection connection) throws InterruptedException { if(connection!=null) { System.out.println("当前有"+useful.getQueueLength()+"个线程等待数据库连接!!" +"可用连接数:"+useful.availablePermits()); synchronized (pool) { pool.addLast(connection); } useful.release(); } } /*从池子拿连接*/ public Connection takeConnect() throws InterruptedException { useful.acquire(); Connection connection; synchronized (pool) { connection = pool.removeFirst(); } return connection; } private static DBPoolNoUseless dbPoolNoUseless = new DBPoolNoUseless(); private static class BusiThread extends Thread{ @Override public void run() { Random r = new Random();//让每个线程持有连接的时间不一样 long start = System.currentTimeMillis(); try { System.out.println("Thread_"+Thread.currentThread().getId() +"_获取数据库连接共耗时【"+(System.currentTimeMillis()-start)+"】ms."); SleepTools.ms(100+r.nextInt(100));//模拟业务操作,线程持有连接查询数据 System.out.println("查询数据完成,归还连接!"); dbPoolNoUseless.returnConnect(new SqlConnectImpl()); } catch (InterruptedException e) { } } } public static void main(String[] args) { for (int i = 0; i < 50; i++) { Thread thread = new BusiThread(); thread.start(); } } }
package cn.enjoyedu.ch1.pool; import cn.enjoyedu.tools.SleepTools; import java.sql.*; import java.util.Map; import java.util.Properties; import java.util.concurrent.Executor; /** *类说明: */ public class SqlConnectImpl implements Connection{ /*拿一个数据库连接*/ public static final Connection fetchConnection(){ return new SqlConnectImpl(); } //忽略其它 }