利用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关键字所使用的锁也是可重入的,两者关于这个的区别不大.两者都是同一个线程每进入一次,锁 ...
随机推荐
- input autocomplete 下拉提示+支持中文
js 代码: $.getJSON("/Foreign/Getforeign_routeEndPoint", function (data) { $(" ...
- 在 Android 中 Intent 的概念及应用
一.显式Intent: startActivity(new Intent(MainActivity.this, 类名.class)); 二.隐式Intent: 1.在AndroidManiFest ...
- C# Best Practices - Specify Clear Method Parameters
Improve parameters parameter order public OperationResult PlaceOrder(Product product, int quantity, ...
- Css静态进度条
图片预览: Css代码: <style> .statusList{width:240px; float:left; line-height:68px;margin:0 2px; text- ...
- php随笔4-thinkphp 学习-ThinkPHP3.1快速入门(2)数据CURD
ThinkPHP3.1快速入门(2)数据CURD 浏览:194739 发布日期:2012/09/05 分类:文档教程 关键字: 快速入门 CURD 上一篇中,我们了解了ThinkPHP的基础部分, ...
- java:字符串的“+”运算
今天在一篇博客里,意外的看到了一段关于java中对字符串的“+”运算的处理(博客原文:http://blog.csdn.net/yirentianran/article/details/2871417 ...
- Agile methodology
ntroduction Waterfall model follows application development in phases with checkpoint and deliverabl ...
- Windows Phone 8初学者开发—第2部分:安装Windows Phone SDK 8.0
原文 Windows Phone 8初学者开发—第2部分:安装Windows Phone SDK 8.0 原文地址:http://channel9.msdn.com/Series/Windows-Ph ...
- 在非MFC程序中使用调试宏 ASSERT(),VERIFY()和 TRACE()
游戏制作已经开始采用C++了,却鲜有人选择使用MFC.但笔者觉得的 ASSERT(),VERIFY()和 TRACE()这几个宏很好用.所以就想自己写一个版本来适应Windows平台下不同的工程类型. ...
- CodeForces - 27E--Number With The Given Amount Of Divisors(反素数)
CodeForces - 27E Number With The Given Amount Of Divisors Submit Status Description Given the number ...