java线程(超时等待+简单数据库连接池)
来源:互联网 发布:程序化交易软件 编辑:程序博客网 时间:2024/05/22 07:55
超时等待模式在一般的等待/通知机制上添加超时控制,使得方法执行时间过长也不会一直造成阻塞,而是在一段时间后返回。
通常java连接数据库时会将其执行过程交由一个线程进行处理,使得在一些I/O操作或需要一定时间运行的行为在后台运行而客户端能立刻对当前的动作做出下一个反应。例如客户端的文件下载上传等往往另开一个线程,而主程序继续监听将要发生的动作,在与数据库交互时,每个用户获得一个专属的线程对其需要的内容进行修改和同步,在并发量较低的情况下,当然可以依次new出一个线程来,但一旦加大了用户数量,或用户频繁地进行操作时,服务端反复创建和回收也会造成比较大的开销,加大系统的负载。(且通常会有很多一些小操作需要服务端快速地进行处理)
线程池的技术能比较合理地解决此问题,预先创建一定量的线程,不由用户对线程直接进行创建控制,而是争取资源获得复用线程进行操作。可以消除频繁创建和消亡所带来的开销(具体线程量和执行速度与多因素有关,在实际使用时应该视情况而定)。
等待超时的模式如下:(伪代码)
//同步对象锁
public synchronized Object get(long mills) throws InterruptedException{
long remaining=mills;
long future=System.currentTimeMills()+mills;
......
...
while((result==null)&&remaining>0){
wait(remaining);
remaining=future-System. currentTimeMills();
}
return result;
}
若remaining<=0 则为已经超时,退出。
————————————————————————————————————————————
简单数据库连接池例子:(引自java并发编程的艺术第4章)
import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;import java.sql.Connection;import java.util.concurrent.TimeUnit;public class ConnectionDriver { static class ConnectionHandler implements InvocationHandler { public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { if (method.getName().equals("commit")) { TimeUnit.MILLISECONDS.sleep(100); } return null; } } // 创建一个Connection的代理,在commit时休眠1秒 public static final Connection createConnection() { return (Connection) Proxy.newProxyInstance(ConnectionDriver.class.getClassLoader(), new Class<?>[] { Connection.class }, new ConnectionHandler()); }}用ConnectionDriver创建返回connect连接,用于加入到线程池集合中
import java.sql.Connection;import java.util.LinkedList;public class ConnectionPool { private LinkedList<Connection> pool = new LinkedList<Connection>(); public ConnectionPool(int initialSize) { if (initialSize > 0) { for (int i = 0; i < initialSize; i++) { pool.addLast(ConnectionDriver.createConnection()); } } } public void releaseConnection(Connection connection) { if (connection != null) { synchronized (pool) { // 添加后需要进行通知,这样其他消费者能够感知到链接池中已经归还了一个链接 pool.addLast(connection); pool.notifyAll(); } } } // 在mills内无法获取到连接,将会返回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); remaining = future - System.currentTimeMillis(); } Connection result = null; if (!pool.isEmpty()) { result = pool.removeFirst(); } return result; } } }}通过构造函数初始化连接的上限,用链式集合进行控制(LinkedList 在处理插入删除方面具有较快效益)
在每返回一个连接之后,在集合中删除,而每回收一个连接则通知所有尚在等待的用户,此刻有空余连接可供使用
若在超时时间范围内依旧没有现有连接可以返回则返回null。
import java.sql.Connection;import java.util.concurrent.CountDownLatch;import java.util.concurrent.atomic.AtomicInteger;public class ConnectionPoolTest { static ConnectionPool pool = new ConnectionPool(10); // 保证所有ConnectionRunner能够同时开始 static CountDownLatch start = new CountDownLatch(1); // main线程将会等待所有ConnectionRunner结束后才能继续执行 static CountDownLatch end; public static void main(String[] args) throws Exception { // 线程数量,可以线程数量进行观察 int threadCount = 50; end = new CountDownLatch(threadCount); int count = 20; AtomicInteger got = new AtomicInteger(); AtomicInteger notGot = new AtomicInteger(); for (int i = 0; i < threadCount; i++) { Thread thread = new Thread(new ConnetionRunner(count, got, notGot), "ConnectionRunnerThread"); thread.start(); } start.countDown(); end.await(); System.out.println("total invoke: " + (threadCount * count)); System.out.println("got connection: " + got); System.out.println("not got connection " + notGot); } static class ConnetionRunner implements Runnable { int count; AtomicInteger got; AtomicInteger notGot; public ConnetionRunner(int count, AtomicInteger got, AtomicInteger notGot) { this.count = count; this.got = got; this.notGot = notGot; } public void run() { try { start.await(); } catch (Exception ex) { } while (count > 0) { try { // 从线程池中获取连接,如果1000ms内无法获取到,将会返回null // 分别统计连接获取的数量got和未获取到的数量notGot Connection connection = pool.fetchConnection(1000); if (connection != null) { try { connection.createStatement(); connection.commit(); } finally { pool.releaseConnection(connection); got.incrementAndGet(); } } else { notGot.incrementAndGet(); } } catch (Exception ex) { } finally { count--; } } end.countDown(); } }}运行结果:(线程数量threadCount与每个访问次数count不同,会影响结果成功与失败的比例)
total invoke: 1000
got connection: 836
not got connection 164
- java线程(超时等待+简单数据库连接池)
- 等待超时模式在数据库连接池中的使用
- 多线程等待(超时)/通知的应用场景-数据库连接池
- Java线程等待、通知简单实例代码
- 等待超时实现简单方法
- java 线程池 超时中断
- java 等待线程/线程池执行完毕
- 关于http socket timeout 超时时间 未设置 导致线程一直在等待(线程饥饿),微信公众号开发过程遇到的。java
- java线程的简单等待与唤醒【synchronized关键字】
- java数据库连接池简单实现
- Java实现控制线程超时的简单方法
- JAVA 线程等待
- 【JAVA】等待子线程
- JAVA处理线程超时
- JAVA处理线程超时
- java 线程超时时间
- JAVA处理线程超时
- java线程超时处理
- cordova 和phonegap搭建Android环境
- JQuery datatables 表头复选框切换页面时保持选中的问题解决
- android源码下载
- 在VMware10中安装CentOS 6.4详解 默认安装是非图形
- ajax实现下拉框联动
- java线程(超时等待+简单数据库连接池)
- Android Monitor中logcat无显示问题的解决
- Java-标识符
- Spring集成ActiveMQ
- 第三方App接入微信登录
- ping命令的应用
- Matlab与线性代数 -- 数组的乘法与除法
- Unity UI框架开发(4)--实现UIWindowCtrl
- NFC 基础