为什么要用数据库连接池

数据库连接是一种关键的、有限的、昂贵的资源,这一点在多用户的网页应用程序中体现得尤为突出。对数据库连接的管理能显著影响到整个应用程序的伸缩性和健壮性,影响到程序的性能指标。数据库连接池正是针对这个问题提出来的。

连接池的基本概念

数据库连接池在初始化时将创建一定数量的数据库连接放到连接池中,这些数据库连接的数量是由最小数据库连接数制约。无论这些数据库连接是否被使用,连接池都将一直保证至少拥有这么多的连接数量。连接池的最大数据库连接数量限定了这个连接池能占有的最大连接数,当应用程序向连接池请求的连接数超过最大连接数量时,这些请求将被加入到等待队列中。数据库连接池的最小连接数和最大连接数的设置要考虑到下列几个因素:
1. 最小连接数
是连接池一直保持的数据库连接,所以如果应用程序对数据库连接的使用量不大,将会有大量的数据库连接资源被浪费。
2. 最大连接数
是连接池能申请的最大连接数,如果数据库连接请求超过此数,后面的数据库连接请求将被加入到等待队列中,这会影响之后的数据库操作。
3. 最小连接数与最大连接数差距
最小连接数与最大连接数相差太大,那么最先的连接请求将会获利,之后超过最小连接数量的连接请求等价于建立一个新的数据库连接。不过,这些大于最小连接数的数据库连接在使用完不会马上被释放,它将被放到连接池中等待重复使用或是空闲超时后被释放。
主流开源数据库连接池
1、C3P0:是一个开放源代码的JDBC连接池,它在lib目录中与Hibernate 一起发布,包括了实现jdbc3和jdbc2扩展规范说明的Connection 和Statement 池的DataSources 对象。
2、Proxool:是一个Java SQL Driver驱动程序,提供了对选择的其它类型的驱动程序的连接池封装。可以非常简单的移植到现存的代码中,完全可配置,快速、成熟、健壮。可以透明地为现存的JDBC驱动程序增加连接池功能。
3、Jakarta DBCP:DBCP是一个依赖Jakartacommons-pool对象池机制的数据库连接池。DBCP可以直接的在应用程序中使用。
4、DDConnectionBroker:是一个简单、轻量级的数据库连接池。
5、DBPool:是一个高效、易配置的数据库连接池。它除了支持连接池应有的功能之外,还包括了一个对象池,使用户能够开发一个满足自己需求的数据库连接池。
6、XAPool:是一个XA数据库连接池。它实现了javax.sql.XADataSource并提供了连接池工具。
7、Primrose:是一个Java开发的数据库连接池。当前支持的容器包括Tomcat4&5、Resin3与JBoss3。它同样也有一个独立的版本,可以在应用程序中使用而不必运行在容器中。Primrose通过一个WEB接口来控制SQL处理的追踪、配置,以及动态池管理。在重负荷的情况下可进行连接请求队列处理。
8、SmartPool:是一个连接池组件,它模仿应用服务器对象池的特性。SmartPool能够解决一些临界问题如连接泄漏(connection leaks)、连接阻塞、打开的JDBC对象(如Statements、PreparedStatements)等。SmartPool的特性包括:
  • 支持多个pool
  • 自动关闭相关联的JDBC对象
  • 在所设定time-outs之后察觉连接泄漏
  • 追踪连接使用情况
  • 强制启用最近最少用到的连接
  • 把SmartPool“包装”成现存的一个pool
9、MiniConnectionPoolManager:是一个轻量级JDBC数据库连接池。它只需要Java1.5(或更高)并且没有依赖第三方包。
10、BoneCP:是一个快速、开源的数据库连接池。帮用户管理数据连接,让应用程序能更快速地访问数据库。比C3P0/DBCP连接池速度快25倍。
11、Druid:Druid不仅是一个数据库连接池,还包含一个ProxyDriver、一系列内置的JDBC组件库、一个SQL Parser。
支持所有JDBC兼容的数据库,包括Oracle、MySql、Derby、Postgresql、SQL Server、H2等。
Druid针对Oracle和MySql做了特别优化,比如:
  • Oracle的PS Cache内存占用优化
  • MySql的ping检测优化
Druid提供了MySql、Oracle、Postgresql、SQL-92的SQL的完整支持,这是一个手写的高性能SQL Parser,支持Visitor模式,使得分析SQL的抽象语法树很方便。
简单SQL语句用时10微秒以内,复杂SQL用时30微秒。
通过Druid提供的SQL Parser可以在JDBC层拦截SQL做相应处理,比如说分库分表、审计等。Druid防御SQL注入攻击的WallFilter,就是通过Druid的SQL Parser分析语义实现的

························································································邪恶的代码分界线···································································································

源码地址:https://github.com/java-rookie-233333/ConnectionPool

首先我们自己先定义一个SuperDataSource类去实现javax.sql.DataSource和

javax.sql.ConnectionPoolDataSource接口,继承的ResourceManagement类是我用来把一需要在SuperDataSource实现的方法转移到父类中去实现

然后我们在定义一个DatabaseConfiguration类,这个类是用来保存数据库连接池的一些设置信息,这个是我在获取数据库连接时候需要用到的信息

这里的信息是在SuperDataSource进行了一个初始化设置

在这里我进行了数据库的信息保存,然后设置到SuperPool中;

SuperDataSource类代码

package com;import java.sql.Connection;
import java.sql.SQLException;import javax.sql.ConnectionPoolDataSource;
import javax.sql.DataSource;
import javax.sql.PooledConnection;import com.pool.SuperPool;
import com.pool.SuperPoolConnection;
import com.uitl.StringUtils;/*** * <p>* Copyright: Copyright (c) 2017* </p>* <p>* Company: 熠道大数据* </p>* * @ClassName: SuperConnectionPool* @Description: TODO(数据库连接池)* @author liuhonbin* @date 2018年4月24日*/public class SuperDataSource extends ResourceManagement implements DataSource,ConnectionPoolDataSource {protected volatile String username;protected volatile String password;protected volatile String jdbcUrl;protected volatile String driverClass;protected volatile int initialSize = 0;protected volatile int minIdle = 0;protected volatile int maxIdle = 0;protected volatile int maxActive = 0;protected volatile long maxWait = 0;protected volatile long waitTime = 1000L;private SuperPool superPool = SuperPool.getInstance();public SuperDataSource() {}public SuperDataSource(String username, String password, String jdbcUrl) {super();this.username = username;this.password = password;this.jdbcUrl = jdbcUrl;}public SuperPoolConnection getSuperPoolConnection() {init();try {return superPool.getSuperPoolConnection(getWaitTime());} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}return null;}public Connection getConnection() throws SQLException {SuperPoolConnection superPoolConnection = getSuperPoolConnection();if(superPoolConnection!=null) {return superPoolConnection;}else {throw new UnsupportedOperationException("Not supported by SuperDataSource");}}public Connection getConnection(String username, String password) throws SQLException {if (this.username == null && this.password == null && username != null && password != null) {this.username = username;this.password = password;return getConnection();}if (!StringUtils.equals(username, this.username)) {throw new UnsupportedOperationException("Not supported by SuperDataSource");}if (!StringUtils.equals(password, this.password)) {throw new UnsupportedOperationException("Not supported by SuperDataSource");}return getConnection();}private void init() {if(superPool.getConfiguration() == null) {DatabaseConfiguration configuration = new DatabaseConfiguration();configuration.setDriverClass(getDriverClass());configuration.setJdbcUrl(getJdbcUrl());configuration.setUsername(getUsername());configuration.setPassword(getPassword());configuration.setInitialSize(getInitialSize());configuration.setMaxActive(getMaxActive());configuration.setMaxIdle(getMaxIdle());configuration.setMaxWait(getMaxWait());configuration.setMinIdle(getMinIdle());superPool.setConfiguration(configuration);}}public PooledConnection getPooledConnection() throws SQLException {SuperPoolConnection superPoolConnection = getSuperPoolConnection();if(superPoolConnection!=null) {return superPoolConnection;}else {throw new UnsupportedOperationException("Not supported by SuperDataSource");}}public PooledConnection getPooledConnection(String user, String password) throws SQLException {if (this.username == null && this.password == null && username != null && password != null) {this.username = username;this.password = password;return getPooledConnection();}if (!StringUtils.equals(username, this.username)) {throw new UnsupportedOperationException("Not supported by SuperDataSource");}if (!StringUtils.equals(password, this.password)) {throw new UnsupportedOperationException("Not supported by SuperDataSource");}return getPooledConnection();}//关闭连接池的时候这里要去进行连接集合的清理,目前未做实现public void close() throws SQLException {// TODO Auto-generated method stub}//****************参数get,set方法分界线******************************************    public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}public String getJdbcUrl() {return jdbcUrl;}public void setJdbcUrl(String jdbcUrl) {this.jdbcUrl = jdbcUrl;}public String getDriverClass() {return driverClass;}public void setDriverClass(String driverClass) {this.driverClass = driverClass;}public int getInitialSize() {return initialSize;}public void setInitialSize(int initialSize) {this.initialSize = initialSize;}public int getMinIdle() {return minIdle;}public void setMinIdle(int minIdle) {this.minIdle = minIdle;}public int getMaxIdle() {return maxIdle;}public void setMaxIdle(int maxIdle) {this.maxIdle = maxIdle;}public int getMaxActive() {return maxActive;}public void setMaxActive(int maxActive) {this.maxActive = maxActive;}public long getMaxWait() {return maxWait;}public void setMaxWait(long maxWait) {this.maxWait = maxWait;}public long getWaitTime() {return waitTime;}public void setWaitTime(long waitTime) {this.waitTime = waitTime;}}

然后定义一个SuperPool类,以下是该类方法属性预览图

SuperPool(这是一个单列模式的类,只会加载一次)

1.initDriver():初始化加载驱动,加载一次后就不会再进行加载

2.getConnection() 获取连接

3.getSuperPoolConnection(long waitTime)获取可用连接(具体实现思路在代码中进行补充)

package com.pool;import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.concurrent.ArrayBlockingQueue;import com.DatabaseConfiguration;public class SuperPool {// 在SuperDataSource.getSuperPoolConnection() 方法中进初始化设置private DatabaseConfiguration configuration;// 已使用连接private ArrayBlockingQueue<SuperPoolConnection> use = new ArrayBlockingQueue<SuperPoolConnection>(1024);// 未使用连接private ArrayBlockingQueue<SuperPoolConnection> duse = new ArrayBlockingQueue<SuperPoolConnection>(1024);// 驱动是否初始化标志位private boolean initDriver = false;private SuperPool() {}// 初始化驱动方法,只会加载一次private void initDriver() {try {Class.forName(configuration.getDriverClass());} catch (ClassNotFoundException e) {// TODO Auto-generated catch blocke.printStackTrace();}// 初始化成功设置为trueinitDriver = true;}private SuperPoolConnection getConnection() {// 判断驱动是否初始化加载if (!initDriver) {initDriver();}Connection conn = null;// 自定义的一个Connection类,实现了javax.sql.PooledConnection, java.sql.Connection 接口SuperPoolConnection superPoolConnection = null;try {conn = DriverManager.getConnection(configuration.getJdbcUrl(), configuration.getUsername(),configuration.getPassword());// 将获取到的连接设置到自定义的Connection实现类中superPoolConnection = new SuperPoolConnection(conn);} catch (SQLException e) {// TODO Auto-generated catch blocke.printStackTrace();}return superPoolConnection;}// 单列模式加载private static class Singteton {private static SuperPool superPool;static {superPool = new SuperPool();}public static SuperPool getInstance() {return superPool;}}public static SuperPool getInstance() {return Singteton.getInstance();}public DatabaseConfiguration getConfiguration() {return configuration;}public void setConfiguration(DatabaseConfiguration configuration) {this.configuration = configuration;}// 获取连接public SuperPoolConnection getSuperPoolConnection(long waitTime) throws InterruptedException {SuperPoolConnection superPoolConnection = null;while (true) {// 如果可用连接和已用连接加起来的数量小于最大连接,才允许去获取连接,否则设置时间挂起if (use.size() + duse.size() <= getConfiguration().getMaxIdle()) {// 如果可用连接小于等于0那就新获取一个连接,返回之前把这个连接放到已用集合中去if (duse.size() <= 0) {superPoolConnection = getConnection();use.put(superPoolConnection);return superPoolConnection;} else {return duse.take();}} else {wait(waitTime);}}}// 增加一个连接到已用连接集合中去public void addUse(SuperPoolConnection use) {this.use.add(use);}// 移除一个已用连接public void removeUse(SuperPoolConnection use) {this.use.remove(use);}// 增加一个可用连接public void addDuse(SuperPoolConnection duse) {this.duse.add(duse);}// 移除一个可用连接public void removeDuse(SuperPoolConnection duse) {this.duse.remove(duse);}}

SuperPoolConnection类,实现了javax.sql.PooledConnection, java.sql.Connection接口,在这个类中进行了连接的回收

package com.pool;import java.sql.Array;
import java.sql.Blob;
import java.sql.CallableStatement;
import java.sql.Clob;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.NClob;
import java.sql.PreparedStatement;
import java.sql.SQLClientInfoException;
import java.sql.SQLException;
import java.sql.SQLWarning;
import java.sql.SQLXML;
import java.sql.Savepoint;
import java.sql.Statement;
import java.sql.Struct;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.Executor;import javax.sql.ConnectionEventListener;
import javax.sql.StatementEventListener;public class SuperPoolConnection  implements javax.sql.PooledConnection, java.sql.Connection {protected Connection connection;//这个类为单列,在此处不会重复加载,还是原来的第一次加载的对象private SuperPool superPool = SuperPool.getInstance();//连接是否关闭标志位boolean isClosed = false; //在类初始化的时候要求传入一个java.sql.Connection,这是在SuperPool.getConnection() 中进行了setpublic SuperPoolConnection(Connection connection) {this.connection = connection;}//这里去判断接口否关闭的方法进行了自定义的转态控制public boolean isClosed() throws SQLException {return isClosed;}//关闭此连接时会进行连接回收操作public void close() throws SQLException {//将当前对象在已用连接集合中进行移除superPool.removeUse(this);//然后在将当前对象加到可用连接集合中superPool.addDuse(this);//次连接的转态Close转态设置为trueisClosed = true;//再将连接设置为nullconnection = null;}public <T> T unwrap(Class<T> iface) throws SQLException {return connection.unwrap(iface);}public boolean isWrapperFor(Class<?> iface) throws SQLException {// TODO Auto-generated method stubreturn connection.isWrapperFor(iface);}public Statement createStatement() throws SQLException {// TODO Auto-generated method stubreturn connection.createStatement();}public PreparedStatement prepareStatement(String sql) throws SQLException {// TODO Auto-generated method stubreturn connection.prepareStatement(sql);}public CallableStatement prepareCall(String sql) throws SQLException {return connection.prepareCall(sql);}public String nativeSQL(String sql) throws SQLException {return connection.nativeSQL(sql);}public void setAutoCommit(boolean autoCommit) throws SQLException {connection.setAutoCommit(autoCommit);      }public boolean getAutoCommit() throws SQLException {return connection.getAutoCommit();}public void commit() throws SQLException {connection.commit();      }public void rollback() throws SQLException {connection.rollback();     }public DatabaseMetaData getMetaData() throws SQLException {// TODO Auto-generated method stubreturn connection.getMetaData();}public void setReadOnly(boolean readOnly) throws SQLException {connection.setReadOnly(readOnly);     }public boolean isReadOnly() throws SQLException {return connection.isReadOnly();}public void setCatalog(String catalog) throws SQLException {connection.setCatalog(catalog);   }public String getCatalog() throws SQLException {return connection.getCatalog();}public void setTransactionIsolation(int level) throws SQLException {connection.setTransactionIsolation(level);     }public int getTransactionIsolation() throws SQLException {return connection.getTransactionIsolation();}public SQLWarning getWarnings() throws SQLException {return connection.getWarnings();}public void clearWarnings() throws SQLException {connection.clearWarnings();}public Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException {return connection.createStatement(resultSetType, resultSetConcurrency);}public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency)throws SQLException {return connection.prepareStatement(sql, resultSetType, resultSetConcurrency);}public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) throws SQLException {return connection.prepareCall(sql, resultSetType, resultSetConcurrency);}public Map<String, Class<?>> getTypeMap() throws SQLException {return connection.getTypeMap();}public void setTypeMap(Map<String, Class<?>> map) throws SQLException {connection.setTypeMap(map);        }public void setHoldability(int holdability) throws SQLException {connection.setHoldability(holdability);       }public int getHoldability() throws SQLException {return connection.getHoldability();}public Savepoint setSavepoint() throws SQLException {return connection.setSavepoint();}public Savepoint setSavepoint(String name) throws SQLException {return connection.setSavepoint(name);}public void rollback(Savepoint savepoint) throws SQLException {connection.rollback(savepoint);       }public void releaseSavepoint(Savepoint savepoint) throws SQLException {connection.releaseSavepoint(savepoint);}public Statement createStatement(int resultSetType, int resultSetConcurrency, int resultSetHoldability)throws SQLException {return connection.createStatement(resultSetType, resultSetConcurrency, resultSetHoldability);}public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency,int resultSetHoldability) throws SQLException {return connection.prepareStatement(sql, resultSetType, resultSetConcurrency, resultSetHoldability);}public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency,int resultSetHoldability) throws SQLException {return connection.prepareCall(sql, resultSetType, resultSetConcurrency, resultSetHoldability);}public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SQLException {return connection.prepareStatement(sql, autoGeneratedKeys);}public PreparedStatement prepareStatement(String sql, int[] columnIndexes) throws SQLException {return connection.prepareStatement(sql, columnIndexes);}public PreparedStatement prepareStatement(String sql, String[] columnNames) throws SQLException {return connection.prepareStatement(sql, columnNames);}public Clob createClob() throws SQLException {return connection.createClob();}public Blob createBlob() throws SQLException {return connection.createBlob();}public NClob createNClob() throws SQLException {return connection.createNClob();}public SQLXML createSQLXML() throws SQLException {return connection.createSQLXML();}public boolean isValid(int timeout) throws SQLException {return connection.isValid(timeout);}public void setClientInfo(String name, String value) throws SQLClientInfoException {connection.setClientInfo(name, value);     }public void setClientInfo(Properties properties) throws SQLClientInfoException {connection.setClientInfo(properties);      }public String getClientInfo(String name) throws SQLException {return connection.getClientInfo(name);}public Properties getClientInfo() throws SQLException {return connection.getClientInfo();}public Array createArrayOf(String typeName, Object[] elements) throws SQLException {return connection.createArrayOf(typeName, elements);}public Struct createStruct(String typeName, Object[] attributes) throws SQLException {return connection.createStruct(typeName, attributes);}public void setSchema(String schema) throws SQLException {connection.setSchema(schema);        }public String getSchema() throws SQLException {return connection.getSchema();}public void abort(Executor executor) throws SQLException {connection.abort(executor);        }public void setNetworkTimeout(Executor executor, int milliseconds) throws SQLException {connection.setNetworkTimeout(executor, milliseconds);      }public int getNetworkTimeout() throws SQLException {return connection.getHoldability();}public Connection getConnection() throws SQLException {return connection;}public void addConnectionEventListener(ConnectionEventListener listener) {// TODO Auto-generated method stub}public void removeConnectionEventListener(ConnectionEventListener listener) {// TODO Auto-generated method stub}public void addStatementEventListener(StatementEventListener listener) {// TODO Auto-generated method stub}public void removeStatementEventListener(StatementEventListener listener) {// TODO Auto-generated method stub}}

代码测试1

这里我们会发现第一次获取连接如果使用完后进行了关闭,第二次进行获取的时候,获取的是同一个连接对象

测试代码2

如果我们第一次获取连接为进行关闭,那么第二次进行连接获取就是新获取一个连接

如果您觉得我的文章还可以,可以给个好评喲,手动滑稽表情

数据库连接池实现原理相关推荐

  1. 面试官:谈谈数据库连接池的原理

    来源:https://dwz.cn/oUF6pKOW 这次我们采取技术演进的方式来谈谈数据库连接池的技术出现过程及其原理,以及当下最流行的开源数据库连接池jar包. 一.早期我们怎么进行数据库操作 1 ...

  2. 3 连接sybase_今日头条面试官:给我说说数据库连接池的原理?

    作者:敦格 来源:https://urlify.cn/ABJbum 这次我们采取技术演进的方式来谈谈数据库连接池的技术出现过程及其原理,以及当下最流行的开源数据库连接池jar包. # 早期我们怎么进行 ...

  3. 谈谈数据库连接池的原理

    这次我们采取技术演进的方式来谈谈数据库连接池的技术出现过程及其原理,以及当下最流行的开源数据库连接池jar包. 一.早期我们怎么进行数据库操作        1.原理:一般来说,java应用程序访问数 ...

  4. 【手写系列】理解数据库连接池底层原理之手写实现

    前言 数据库连接池的基本思想是:为数据库连接建立一个"缓冲池",预先在池中放入一定数量的数据库连接管道,需要时,从池子中取出管道进行使用,操作完毕后,再将管道放入池子中,从而避免了 ...

  5. java 连接池技术_java数据库连接池技术原理(浅析)

    在执行数据库SQL语句时,我们先要进行数据连接:而每次创建新的数据库的连接要消耗大量的资源,这样,大家就想出了数据库连接池技术.它的原理是,在运行过程中,同时打开着一定数量的数据库连接,形成数据连接池 ...

  6. 数据库连接池的原理没你想得这么复杂

    来源 | 犀牛饲养员的技术笔记 封图| CSDN 下载于视觉中国 背景介绍 数据库连接池和线程池等池技术存在的意义都是为了解决资源的重复利用问题.在计算机里,创建一个新的资源往往开销是非常大的.而池技 ...

  7. 【MySQL】数据库连接池的原理及实现

    本专栏将从基础开始,循序渐进,讲解数据库的基本概念以及使用,希望大家都能够从中有所收获,也请大家多多支持. 专栏地址: 数据库必知必会 相关软件地址:软件地址 如果文章知识点有错误的地方,请指正!大家 ...

  8. Java数据库连接池实现原理

    https://blog.csdn.net/tuke_tuke/article/details/51532510 一般来说,Java应用程序访问数据库的过程是: ①装载数据库驱动程序: ②通过jdbc ...

  9. 数据库连接池工作原理

    在实际应用开发中,特别是在WEB应用系统中,如果JSP.Servlet或EJB使用JDBC直接访问数据库中的数据,每一次数据访问请求都必须经历建立数据库连接.打开数据库.存取数据和关闭数据库连接等步骤 ...

  10. 说说数据库连接池工作原理和实现方案?

    **工作原理:**JAVA EE服务器启动时会建立一定数量的池连接,并一直维持不少于此数目的池连接.客户端程序需要连接时,池驱动程序会返回一个未使用的池连接并将其表记为忙.如果当前没有空闲连接,池驱动 ...

最新文章

  1. 写给大忙人看的死锁详解
  2. python编程语法大全-python语法汇总
  3. 《图书管理系统——java》
  4. c语言考试题及答案 大一,大一C语言期末考试试题
  5. 美观大气!一款基于 Spring Boot 开发 OA 开源产品
  6. 循环 Request.ServerVariables
  7. 解决VS+QT无法生成moc文件的问题
  8. md 文件编辑 Markdown 使用教程
  9. iOS视频裁剪、拼接、添加水印、添加背景音乐
  10. 创作原创歌词的韵律十三辙与韵脚押韵方法
  11. windows系统重装(绝对干净)、备份还原、引导修复步骤
  12. 【软件工程系列】结构化需求分析
  13. SonarQube 初探
  14. 将HTML 转为pdf
  15. 一剂拯救“国足”的终极药方:全面 AI 化
  16. Java基础篇--继承(inherit),多态(Polymorphism)
  17. 微软拥抱开源_拥抱开源作为视觉艺术家
  18. 十三道Python练习题
  19. 从3元/条的个人信息买卖看企业数据安全建设
  20. 【C++】%d,%05d,%-5d,%.5d的区分

热门文章

  1. XJOI一级题库所有题解(传送门)
  2. 三轴加速度传感器和六轴惯性传感器_六轴传感器和三轴传感器的区别在哪
  3. 用Python实现一个简单的加密程序
  4. flex 3 格式化组件
  5. 最新Mac安装/卸载pip教程
  6. 外点惩罚函数法matlab程序例子,外点罚函数优化实例.doc
  7. c语言中优先级顺序表
  8. html5脑图_HTML5制作思维导图
  9. 多源数据融合:大数据分析的瓶颈
  10. java application.doevents_关于Application.DoEvents()的小研究