In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-02-28 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Database >
Share
Shulou(Shulou.com)06/01 Report--
1. I believe many people already know what connection pooling is used for after reading this article. Yes, database connection pool is to establish a "buffer pool" for database connections, put a certain number of connections in the "buffer pool" in advance, and take one out of the "buffer pool" when you need to establish a database connection. Put it in after use. The advantage of this is that frequent database connections can avoid taking up a lot of system resources.
two。 Common database connection pools are: dbcp,c3p0, Ali's Druid. Well, without much gossip, this article aims to deepen your understanding of connection pooling. The database I chose here is mysql.
3. Let's first talk about the process of connection pooling:
First of all, there must be a configuration file! When we use data sources in our daily projects, we need to configure database drivers, database usernames, database passwords, and connections. These four roles are absolutely indispensable.
I believe many people already know what connection pooling is used for after reading this article. Yes, database connection pool is to establish a "buffer pool" for database connections, put a certain number of connections in the "buffer pool" in advance, and take one out of the "buffer pool" when you need to establish a database connection. Put it in after use. The advantage of this is that frequent database connections can avoid taking up a lot of system resources.
Common database connection pools are: dbcp,c3p0, Ali's Druid. Well, without much gossip, this article aims to deepen your understanding of connection pooling. The database I chose here is mysql.
Let's first talk about the process of connection pooling:
First of all, there must be a configuration file! When we use data sources in our daily projects, we need to configure database drivers, database usernames, database passwords, and connections. These four roles are absolutely indispensable.
# File name: db.properties
Jdbc.driver=com.mysql.jdbc.Driver
Jdbc.url=jdbc:mysql://localhost:3306/ssm
Jdbc.username=root
Jdbc.password=lfdy
Jdbc.initSize=3
Jdbc.maxSize=10
# whether to start the check
Jdbc.health=true
# check delay time
Jdbc.delay=3000
# interval
Jdbc.period=3000
Jdbc.timeout=100000
two。 We will write a class based on the above configuration file db.properties and load its properties
Public class GPConfig {
Private String driver
Private String url
Private String username
Private String password
Private String initSize
Private String maxSize
Private String health
Private String delay
Private String period
Private String timeout
/ / omit the set and get methods / / write a constructor to initialize properties in the constructor
Public GPConfig () {
Properties prop = new Properties ()
/ / this seems to be the only way to read files in a maven project.
InputStream stream = this.getClass () .getResourceAsStream ("/ resource/db.properties")
Try {
Prop.load (stream)
/ / call the setter method in the constructor. There are many attributes here, so we certainly do not call it step by step. It is recommended to use the reflection mechanism.
For (Object obj: prop.keySet ()) {
/ / get the parameter, how to get it? Isn't this the key removal of the configuration file? what should be removed? Remove "jdbc."
String fieldName = obj.toString () .replace ("jdbc.")
Field field = this.getClass () .getDeclaredField (fieldName)
Method method = this.getClass () .getMethod (toUpper (fieldName), field.getType ())
Method.invoke (this, prop.get (obj))
}
} catch (Exception e) {
E.printStackTrace ()
}
}
/ / read the key in the configuration file and convert it to the correct set method
Public String toUpper (String fieldName) {
Char [] chars = fieldName.toCharArray ()
Chars [0]-= 32; / / how to capitalize the first letter of a string
Return "set" + new String (chars)
}
}
3. All right, we've written the configuration file, and the class that loads the configuration file has been written. What's next? Recall that before we had a connection pool, did we use Class.forName (), getConnection, and so on to connect to the database? So, let's next write a class with methods to create a connection and get a connection.
Public class GPPoolDataSource {
/ / load configuration class
GPConfig config = new GPConfig ()
/ / write a parameter to mark how many active connections there are currently
Private AtomicInteger currentActive = new AtomicInteger (0)
/ / create a collection, for what? It is used to store connections. After all, we need to create initSize connections when we initialize them.
/ and, when we release the connection, we put the connection in here.
Vector freePools = new Vector ()
/ / connection pool in use
Vector usePools = new Vector ()
/ / initialization in the constructor
Public GPPoolDataSource () {
Init ()
}
/ / initialization method
Public void init () {
Try {
/ / do we have to load jdbc every time? Definitely not. Just load it once.
Class.forName (config.getDriver ())
For (int I = 0; I
< Integer.valueOf(config.getInitSize());i++){ Connection conn = createConn(); freePools.add(conn); } } catch (ClassNotFoundException e) { e.printStackTrace(); } check(); } //创建连接 public synchronized Connection createConn(){ Connection conn = null; try { conn = DriverManager.getConnection(config.getUrl(), config.getUsername(), config.getPassword()); currentActive.incrementAndGet(); System.out.println("创建一个连接, 当前的活跃的连接数目为:"+ currentActive.get()+" 连接:"+conn); } catch (SQLException e) { e.printStackTrace(); } return conn; } /** * 创建连接有了,是不是也应该获取连接呢? * @return */ public synchronized GPPoolEntry getConn(){ Connection conn = null; if(!freePools.isEmpty()){ conn = freePools.get(0); freePools.remove(0); }else{ if(currentActive.get() < Integer.valueOf(config.getMaxSize())){ conn = createConn(); }else{ try { System.out.println("连接池已经满了,需要等待..."); wait(1000); return getConn(); } catch (InterruptedException e) { e.printStackTrace(); } } } GPPoolEntry poolEntry = new GPPoolEntry(conn, System.currentTimeMillis()); //获取连接干嘛的?不就是使用的吗?所以,每获取一个,就放入正在使用池中 usePools.add(poolEntry); return poolEntry; } /** * 创建连接,获取连接都已经有了,接下来就是该释放连接了 */ public synchronized void release(Connection conn){ try { if(!conn.isClosed() && conn != null){ freePools.add(conn); } System.out.println("回收了一个连接,当前空闲连接数为:"+freePools.size()); } catch (SQLException e) { e.printStackTrace(); } } //定时检查占用时间超长的连接,并关闭 private void check(){ if(Boolean.valueOf(config.getHealth())){ Worker worker = new Worker(); new java.util.Timer().schedule(worker, Long.valueOf(config.getDelay()), Long.valueOf(config.getPeriod())); } } class Worker extends TimerTask{ @Override public void run() { System.out.println("例行检查..."); for(int i = 0; i < usePools.size();i++){ GPPoolEntry entry = usePools.get(i); long startTime = entry.getUseStartTime(); long currentTime = System.currentTimeMillis(); if((currentTime-startTime)>Long.valueOf (config.getTimeout ()) {
Connection conn = entry.getConn ()
Try {
If (conn! = null & &! conn.isClosed ()) {
Conn.close ()
UsePools.remove (I)
CurrentActive.decrementAndGet ()
System.out.println ("timeout connection found, forcibly closed, current active connections:" + currentActive.get ())
}
} catch (SQLException e) {
E.printStackTrace ()
}
}
}
}
}
}
4. In the check () method above, to check for timeouts, we need to use a wrapper class
Public class GPPoolEntry {
Private Connection conn
Private long useStartTime
Public Connection getConn () {
Return conn
}
Public void setConn (Connection conn) {
This.conn = conn
}
Public long getUseStartTime () {
Return useStartTime
}
Public void setUseStartTime (long useStartTime) {
This.useStartTime = useStartTime
}
Public GPPoolEntry (Connection conn, long useStartTime) {
Super ()
This.conn = conn
This.useStartTime = useStartTime
}
}
5. All right, everything is ready. Let's write a test class and test it.
Public class GPDataSourceTest {
Public static void main (String [] args) {
GPPoolDataSource dataSource = new GPPoolDataSource ()
Runnable runnable = ()-> {
Connection conn = dataSource.getConn () .getConn ()
System.out.println (conn)
}
ExecutorService executorService = Executors.newFixedThreadPool (5)
For (int I = 0; I
< 60; i++) { executorService.submit(runnable); } executorService.shutdown(); } } 4.好了,我给下我的结果: 5.总结下,这个手写连接池部分,其实我也是学习的别人的,所以有很多东西不熟悉,也有许多漏洞,现在我先说下我需要完善的地方: 反射机制 读取properties文件 线程池 线程 集合VectorWelcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.