利用java concurrent 包实现日志写数据库的并发处理
一、概述
在很多系统中,往往需要将各种操作写入数据库(比如客户端发起的操作)。
最简单的做法是,封装一个公共的写日志的api,各个操作中调用该api完成自己操作日志的入库。但因为入数据库效率比较低,如果每个操作自己入库,则会影响响应速度。而且当操作并发度很高时,往往同时有多个线程在写数据库,也会对系统有影响。
考虑的解决方案是,这个api并不实际完成入库,而是将每个操作日志信息写到一个公共的缓存中,然后应用系统起了一个独立的线程(一直运行)在后台进行入库。如果当前缓存中有记录,就写库,没有记录,就堵塞住。
这里关键的是要有一个缓存日志的数据结构,我们这里使用java current包中的并发数据结构LinkedBlockingDeque类。
二、具体代码
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.LinkedBlockingDeque; public class LogManager implements Runnable {
//定义缓存数据结构,支持并发操作
private static LinkedBlockingDeque<ActionLog> list = new LinkedBlockingDeque<ActionLog>();
static{
//创建并启动线程,该线程实现日志的入库
new Thread(new LogManager()).start();
}
public static void addActionLog(ActionLog log) {
list.add(log);
} @Override
public void run() {
List<ActionLog> items = new ArrayList<ActionLog>();
while (true) {
//从缓存中取出1条日志,但不从缓存中删除。用于检查队列中是否有数据
ActionLog item = list.peek();
if (item == null && items.size() > 0) {
//item为null说明缓存中没有日志了,这时如果临时队列items中有记录,就可以批量入库了
work(items);
}
//从缓存中取出并删除最前面的日志,如果无数据,在堵塞
ActionLog result = deleteItem();
//将取出的记录放到临时队列中
items.add(result);
}
} private ActionLog deleteItem() {
ActionLog result = null;
try {
//取出并删除最前面的一条数据,如果缓存中无数据,则堵塞住
result = list.takeFirst();
} catch (InterruptedException e) {
e.printStackTrace();
}
return result;
} private void work(List<ActionLog> items) {
//TODO 完成入库。这里代码没有提供
//入库后删除临时队列中记录
items.clear();
} }
各种工作线程调用 addActionLog 方法将要入库的日志放到缓存中。由LogManager通过自己的线程控制入库。
三、小结
上述代码虽然简单,但很好的解决了前面提出的问题。不过这个解决方案存在一个问题。
如果说系统产生日志的速度超过了单个线程入库的速度,上述代码就有问题。就会造成该线程不停地入库。
这时就需要考虑增加额外的处理速度,如增加入库线程。
所以上述代码,只适合并发日志量不是特别大的情况下的场景。
利用java concurrent 包实现日志写数据库的并发处理的更多相关文章
- java concurrent包的学习(转)
java concurrent包的学习(转) http://my.oschina.net/adwangxiao/blog/110188 我们都知道,在JDK1.5之前,Java中要进行业务并发时,通常 ...
- Java网络编程:利用Java mail包发送电子邮件
下面代码是利用Java mail包封装了一个发送邮件的类 import java.io.File; import java.util.ArrayList; import java.util.Date; ...
- java Concurrent包学习笔记(四):BlockingQueue
一.BlockingQueue概述 1.阻塞的含义 BlockingQueue即阻塞队列,从阻塞这个词可以看出,在某些情况下对阻塞队列的访问可能会造成阻塞.被阻塞的情况主要有如下两种: ,当一个线程对 ...
- java concurrent包的实现原理
由于java的CAS同时具有 volatile 读和volatile写的内存语义,因此Java线程之间的通信现在有了下面四种方式: A线程写volatile变量,随后B线程读这个volatil ...
- java Concurrent包学习笔记(一):ExecutorService
一.介绍 ExecutorService是java.util.concurrent包中的一个线程池实现接口.其有两个实现类: 1)ThreadPoolExecutor:普通线程池通过配置线程池大小,能 ...
- 利用“Java同包同名类执行顺序”取消Java 网站应用程序Licence验证
如果是在tomcat里运行,lib目录下一大堆的JAR包,不同的JAR包里可能会有相同的包名类名,JRE按照JAR名字的字母顺序加载JAR文件,同名类如果已加载,则后面的同名类会忽略. 公司购买的一款 ...
- java Concurrent包学习笔记(六):Exchanger
一.概述 Exchanger 是一个用于线程间协作的工具类,Exchanger用于进行线程间的数据交换,它提供一个同步点,在这个同步点,两个线程可以交换彼此的数据.这两个线程通过exchange 方法 ...
- java Concurrent包学习笔记(五):Semaphore
一.Semaphore 是什么 信号量Semaphore是一个并发工具类,用来控制可同时并发的线程数,其内部维护了一组虚拟许可,构造函数初始化的时候可以指定许可的总数量 每次线程执行操作时先通过ac ...
- java Concurrent包学习笔记(三):ReentrantLock
一.可重入性的理解 从名字上理解,ReenTrantLock的字面意思就是再进入的锁,其实synchronized关键字所使用的锁也是可重入的,两者关于这个的区别不大.两者都是同一个线程每进入一次,锁 ...
随机推荐
- 使用RadioGroup与RadioButton实现多选一
RadioGroup是RadioButton的集合, RadioGroup里面可以包含很多RadioButton,提供多选一机制,只能选择其中一个 RadioGroup的orientation(方向) ...
- MongoDB Linux下的安装和启动(转)
1. 下载MongoDB,此处下载的版本是:mongodb-linux-i686-1.8.1.tgz.tar. http://fastdl.mongodb.org/linux/mongodb-linu ...
- mongoDB初接触
首先去官网http://www.mongodb.org/ 下载mongoDB 下载后解压D:\mongodb 创建两个新文件夹data以及log 新建一个文件命名为mongodb.cfg dbpath ...
- position relative和absolute区别
看这个博客 说的很详细http://blog.sina.com.cn/s/blog_647a022e0101b2gn.html 总的来说 这两个属性都是通过增加left和right偏离原来的位置 但 ...
- QListWidget 去掉选中项
1.先去掉选中项的虚线框: 设置为无焦点:把FocusPolicy设置成:NoFocus 2.设置QListWidgetItem标志 调用setFlags函数,去掉Qt::ItemIsSelectab ...
- Socket 基础解析使用ServerSocket建立聊天服务器
很简单的教程哦! 1.socket 简介 Socket 又称"套接字",应用程序通常通过"套接字"向网络发出请求或者应答网络请求.ServerSocket 用于 ...
- 质因数分解的rho以及miller-rabin
一.前言 质因数分解,是一个在算法竞赛里老生常谈的经典问题.我们在解决许多问题的时候需要用到质因数分解来辅助运算,而且质因数分解牵扯到许许多多经典高效的算法,例如miller-rabin判断素数算法, ...
- CSS中border-style的属性
属性可能的值 值 描述 none 定义无边框. hidden 与 "none" 相同.不过应用于表时除外,对于表,hidden 用于解决边框冲突. dotted 定义点状边框.在大 ...
- ListView下拉刷新及上拉更多两种状态
一.前言: 很多应用都会用到ListView,当然如果是iOS就会用UITableViewController,这两个控件在不同的OS上,功能是一样的,只是有些细微的不同(iOS的UITableVie ...
- asp.net中MVC多语言包的使用
Global.asax.cs文件 protected void Application_AcquireRequestState(object sender, EventArgs e) { if (Ht ...