java mysql 并发写入_利用java concurrent 包实现日志写数据库的并发处理

本文介绍了一种高效处理高并发系统日志的方法:通过使用LinkedBlockingDeque缓存日志,然后由独立线程批量写入数据库,有效提升了系统的响应速度。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、概述

在很多系统中,往往需要将各种操作写入数据库(比如客户端发起的操作)。

最简单的做法是,封装一个公共的写日志的api,各个操作中调用该api完成自己操作日志的入库。但因为入数据库效率比较低,如果每个操作自己入库,则会影响响应速度。而且当操作并发度很高时,往往同时有多个线程在写数据库,也会对系统有影响。

考虑的解决方案是,这个api并不实际完成入库,而是将每个操作日志信息写到一个公共的缓存中,然后应用系统起了一个独立的线程(一直运行)在后台进行入库。如果当前缓存中有记录,就写库,没有记录,就堵塞住。

这里关键的是要有一个缓存日志的数据结构,我们这里使用java current包中的并发数据结构LinkedBlockingDeque类。

二、具体代码

importjava.util.ArrayList;importjava.util.List;importjava.util.concurrent.LinkedBlockingDeque;public class LogManager implementsRunnable {//定义缓存数据结构,支持并发操作

private static LinkedBlockingDeque list = new LinkedBlockingDeque();static{//创建并启动线程,该线程实现日志的入库

new Thread(newLogManager()).start();

}public static voidaddActionLog(ActionLog log) {

list.add(log);

}

@Overridepublic voidrun() {

List items = new ArrayList();while (true) {//从缓存中取出1条日志,但不从缓存中删除。用于检查队列中是否有数据

ActionLog item =list.peek();if (item == null && items.size() > 0) {//item为null说明缓存中没有日志了,这时如果临时队列items中有记录,就可以批量入库了

work(items);

}//从缓存中取出并删除最前面的日志,如果无数据,在堵塞

ActionLog result =deleteItem();//将取出的记录放到临时队列中

items.add(result);

}

}privateActionLog deleteItem() {

ActionLog result= null;try{//取出并删除最前面的一条数据,如果缓存中无数据,则堵塞住

result =list.takeFirst();

}catch(InterruptedException e) {

e.printStackTrace();

}returnresult;

}private void work(Listitems) {//TODO 完成入库。这里代码没有提供//入库后删除临时队列中记录

items.clear();

}

}

各种工作线程调用 addActionLog 方法将要入库的日志放到缓存中。由LogManager通过自己的线程控制入库。

三、小结

上述代码虽然简单,但很好的解决了前面提出的问题。不过这个解决方案存在一个问题。

如果说系统产生日志的速度超过了单个线程入库的速度,上述代码就有问题。就会造成该线程不停地入库。

这时就需要考虑增加额外的处理速度,如增加入库线程。

所以上述代码,只适合并发日志量不是特别大的情况下的场景。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值