我用LinkedBlockingQueue写的连接池
Posted Hmake
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了我用LinkedBlockingQueue写的连接池相关的知识,希望对你有一定的参考价值。
什么是连接池呢?
我们登陆上某个网站,去修改个人信息、点击下单、修改购买商品的数量......当我们做这些操作时候,
我们已经连接上数据库并修改、增加、删除数据库中的数据,完成操作后,关闭连接(避免占用资源)。
如果很多人访问这个网站并进行操作,那要创建很多个连接,而且只操作一次就关闭,这会显著的影响系统的
性能。连接池 就为解决这个难题应运而生。
连接池:
在系统初始化的时候,将数据库连接作为对象存放在内存中。当用户要访问数据库时,取出一个连接,
完成操作后归还到池中,等待下个用户使用。连接的创建、断开都由池来管理。我们可以设置连接池的参
数控制初始连接数、连接的上下限数、最大空闲时间......这项技术明显的提高对数据库操作的性能。
线程池:
package org3.pool; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.sql.Connection; import java.util.concurrent.LinkedBlockingQueue; /** * Created by Administrator on 2016/11/25. * 编写一个线程池 */ public class Pool { private int minSize = 1; //定义最小连接数,默认为2 private int maxSize = 2; //定义最大连接数,默认为4 private int fetchCount = minSize; //记录从数据库抓取的连接数 private LinkedBlockingQueue<Connection> pool; //定义一个阻塞队列,充当连接池 public void setMinSize(int minSize) { this.minSize = minSize; this.fetchCount = minSize; } public void setMaxSize(int maxSize) { this.maxSize = maxSize; } //初始化线程池方法 public void initPool() { //初始化连接池的最大值 pool = new LinkedBlockingQueue<>( maxSize ); //预先存放minSize个连接 for ( int i = 0 ; i < minSize ; i++ ) { pool.add( DBUtil.getConnection() ); } } //从数据库抓取连接方法 public synchronized Connection getConnection() { //检查连接池状况,如果检查未通过将直接引发异常,程序终止 checkFetch(); Connection conn = null; try { conn = getProxyConnection(); } catch (InterruptedException e) { e.printStackTrace(); } return conn; } //检查连接池的状况 private void checkFetch() { //当连接池大小为0 且 连接记录数还没达到最大值时 if ( pool.isEmpty() && fetchCount < maxSize ) { pool.add( DBUtil.getConnection() ); } } //从连接池获取连接,并将获取的连接创建一个代理对象 private Connection getProxyConnection() throws InterruptedException { //先从池中获取未代理的连接对象 Connection conn = pool.take(); //将获取的链接创建代理对象 return createProxy( conn ); } //使用内部类来实现InvocationHandler private Connection createProxy( Connection conn ) { return ( Connection )Proxy.newProxyInstance( Connection.class.getClass().getClassLoader(), new Class[] { Connection.class }, new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //如果客户端调用的是close方法,就将连接放回连接池 if( "close".equals(method.getName() ) ) { pool.put( conn ); fetchCount--; } //如果是Connection其他的方法,将正常回调,也就是放行 return method.invoke(conn,args); } }); } //查看连接池当前连接数 public int size() { return pool.size(); } }
DBUtil:
package org3.pool; import java.sql.*; /** * Created by Administrator on 2016/11/25. */ public class DBUtil { private static String driver = "oracle.jdbc.driver.OracleDriver"; //数据库驱动 private static String url = "jdbc:oracle:thin:@localhost:1521:orcl"; //数据库的资源地址 private static String userName = "mark"; //用户名 private static String password = "mark"; //密码 static { try { Class.forName( driver ); } catch (ClassNotFoundException e) { e.printStackTrace(); } } public static Connection getConnection() { Connection conn = null; try { conn = DriverManager.getConnection( url, userName, password ); } catch (SQLException e) { e.printStackTrace(); } return conn; } //main方法(用于测试) public static void main(String[] args) { System.out.println( getConnection() ); } }
编写一个线程:
package org3.pool; import java.sql.Connection; import java.sql.SQLException; /** * Created by Administrator on 2016/11/26. * 编写线程1 */ public class User1 extends Thread { //定义连接池对象 private Pool pool; public User1( Pool pool ) { this.pool = pool; } //重写Thread的run方法 @Override public void run() { Connection conn = pool.getConnection(); System.out.println(Thread.currentThread().getName() + "获取了一个连接:" + conn); try { Thread.sleep( 500 ); conn.close(); System.out.println(Thread.currentThread().getName() + "归还了一个连接: " + conn); } catch (Exception e) { e.printStackTrace(); } } }
main方法:
package org3.pool; import java.sql.SQLException; /** * Created by Administrator on 2016/11/25. * main方法 */ public class Main { public static void main(String[] args) throws SQLException { //实例化连接池对象 Pool pool = new Pool(); //给连接池设置属性 pool.setMinSize( 2 ); pool.setMaxSize( 5 ); //初始化连接池 pool.initPool(); for( int i = 0; i < 10; i++ ){ User1 u1 = new User1( pool ); u1.start(); } try { Thread.sleep( 10000 ); System.out.println( "线程大小= " + pool.size() ); } catch (InterruptedException e) { e.printStackTrace(); } } }
运行结果:
-------------------------------------------------------------------------
以上是关于我用LinkedBlockingQueue写的连接池的主要内容,如果未能解决你的问题,请参考以下文章
django 部署都阿里云 怎么部署呀 我用的是pycharm写的 写完了 是直接通过FILEzilla 上传吗
Java&Go高性能队列之LinkedBlockingQueue性能测试#yyds干货盘点#
我用delphi写的二层的仓库软件,怎么才能在外网访问我的软件,路由器上有固定ip