摘要:通过交换指针的方式实现两个缓冲区的功能互换,十分巧妙,令人称赞。

本文分享自华为云社区《奇妙的双缓冲机制写日志(Java实现)》,作者: 洛叶飘 。

写日志面临的问题

写日志在Web程序中是一个十分基础与常见的需求,其对性能的要求很高。主要需要处理以下问题:

  1. 多线程并发,需要保证顺序性。
  2. 高配IO操作,但IO操作相比其他指令耗时长,性能低。

即一方面需要面对程序端高配的日志写请求,一方面需要受限于系统磁盘相对缓慢写入文件,应该如何处理呢。

双缓冲区

因此,引入双缓冲区机制,一个缓冲区存储应用程序端发送的日志,按照时间顺序依次存储;另一个缓冲区负责向低层磁盘发送写文件请求。

写文件请求执行相对较慢,因此当写文件执行完毕后,通知管理程序,此时可以将另一个缓冲区内容写入磁盘了。

双缓冲区的奇妙之处就在于,两个缓冲区的交换,是通过交换指针来实现的,非常的高效。

部分实现代码如下(其他部分逻辑代码已省略)。

双缓冲区代码,不使用Java现有的线程安全类,后续通过加锁保证数据安全。

// 负责接收应用程序发来的日志
LinkedList<String> currentBuffer = new LinkedList<>();// 负责将数据同步到磁盘
LinkedList<String> syncBuffer = new LinkedList<>();

第一个缓冲区,接收应用程序高速写日志请求

public void log(String content) {// 加锁保证第一个缓冲区synchronized(this) {// 将log写入内存缓冲中,这里不会直接刷入磁盘文件currentBuffer.add(content);}// 将缓冲区中的内容刷到磁盘logSync();
}

第二缓冲区,向磁盘写日志,并在写入后交换缓冲区指针

private void logSync() {synchronized(this) {// 当前在刷内存缓冲到磁盘中去if (isSyncRunning) {// 判断是否第二个缓冲区还在刷while (isSyncRunning) {try {// 释放锁,即允许第一个缓冲区继续接收日志缓存, 然后等待被唤醒wait(2000);} catch (Exception e) {e.printStackTrace();}}// 此时没有人在写磁盘}// 交换缓冲区指针setReadyToSync();// 设置当前正在同步到磁盘的标志位isSyncRunning = true;}// 刷磁盘,性能最低,不能加锁logBuffer.flush();synchronized(this) {// 同步完磁盘之后,将标志位复位isSyncRunning = false;// 唤醒其他等待刷磁盘的线程notifyAll();}
}

交换缓冲区指针,功能变更

public void setReadyToSync() {LinkedList<String> tmp = currentBuffer;currentBuffer = syncBuffer;syncBuffer = tmp;
}

奇妙之处

两个缓冲区各自处理,互不干扰

两个缓冲区很好的解决了应用程序的“快速、多线程”与IO操作的“缓慢,单线程”的矛盾。应该说,引入双缓冲区是一个显而易见的方式。

缓冲区交换

通过交换指针的方式实现两个缓冲区的功能互换,十分巧妙,令人称赞。

总结

你知道吗?电视机里也在用着双缓冲机制

点击关注,第一时间了解华为云新鲜技术~

今儿新学会一个写日志技能:双缓冲机制相关推荐

  1. QT5开发及实例学习之十七Qt5双缓冲机制

    文章目录 一.原理与设计 二.绘图区的实现 三.主窗口的实现 一.原理与设计   所谓双缓冲机制,是指在绘制控件时,首先将要绘制的内容绘制在一个图片中,再将图片一次性地绘制到控件上.在早期的 Qt 版 ...

  2. Linux-FrameBuffer双缓冲机制显示图像

    1. 液晶屏的基本概念 像素: 屏幕上显示颜色的最小单位,英文叫 pixel.注意,位图(如jpg.bmp等格式的常见图片)也是由一个个的像素点构成的,跟屏幕的像素点的概念一样.原理上讲,将一张位图显 ...

  3. Android SurfaceView的双缓冲机制,引起的闪屏问题

    SurfaceView相关目录 SurfaceView要点 SurfaceView拥有独立的Surface(绘图表面) SurfaceView是用Zorder排序的,他默认在宿主Window的后面,S ...

  4. 关于Surface的底层双缓冲机制学习

    双缓冲机制 问题的由来 CPU访问内存的速度要远远快于访问屏幕的速度.如果需要绘制大量复杂的图像时,每次都一个个从内存中读取图形然后绘制到屏幕就会造成多次地访问屏幕,从而导致效率很低.这就跟CPU和内 ...

  5. android缓冲机制,Android自定义View之双缓冲机制和SurfaceView

    Android自定义View系列 双缓冲机制 问题的由来 CPU访问内存的速度要远远快于访问屏幕的速度.如果需要绘制大量复杂的图像时,每次都一个个从内存中读取图形然后绘制到屏幕就会造成多次地访问屏幕, ...

  6. MFC---定时器和双缓冲机制绘制旋转的金刚石图案

    双缓冲原理 MFC中绘制动画的基本思路是在固定时间间隔内绘制图像,然后擦除旧图像再绘制新图像,这样连续         起来就在人类的视觉上形成动画.为了实现这种"绘制-擦除-再绘制&quo ...

  7. 多线程异步日志系统,高效、强悍的实现方式-双缓冲

    作 者:道哥,10+年嵌入式开发老兵,专注于:C/C++.嵌入式.Linux. 目录 文章目录 单片机中常用的环形缓冲区 多线程异步日志:双缓冲机制 双缓冲机制为什么高效 尽可能的降低 Lock 的时 ...

  8. c语言双缓冲怎么用,C语言游戏编程:GDI怎么实现双缓冲绘图去掉闪烁

    在上篇文章中将我要用 C语言重新写一个俄罗斯方块 ,使用的是GDI的绘图模式(目前正在移植到DX上去,想添加一些更好友好的动画).数据与动画分离,动画的帧率保持在30左右.但是绘图的时候画面出现了强烈 ...

  9. EGE基础入门篇(九):双缓冲与手动渲染

    EGE专栏:EGE专栏 上一篇:EGE基础入门篇(八):清屏与重绘 下一篇: 文章目录 一.双缓冲机制 1. 单缓冲绘图 1.1 单缓冲绘图的缺点 1.2 系统读取帧缓冲 2. 双缓冲绘图 2.1 双 ...

最新文章

  1. Linux下互斥量与条件变量详细解析
  2. Kingbase和PostgreSQL中如何查看当前连接的进程信息
  3. 23.C语言中#if 0,#if 1,#else,#endif的作用
  4. Spring AOP底层实现原理
  5. MyBatis基本配置和实践(三)
  6. 软工总结暨团队成员自评(胡骏)
  7. 谷歌停止对android更新,谷歌停止华为使用安卓系统? 可能影响新系统版本更新?...
  8. python参数检查类型_Python类型检查
  9. SQL Server中的联合主键、聚集索引、非聚集索引、mysql 联合索引
  10. 凸优化有关的数值线性代数知识 作业题
  11. Ubuntu18.04 Xfce桌面环境配置中文输入法
  12. 面向Web应用的并发压力测试工具——Locust实用攻略
  13. 我裂开了,教给他如何搭建和使用代理服务器,他居然用来做这么不正经的事(爬虫,代理ip)
  14. ABP .Net Core 日志组件集成使用NLog
  15. 斐波那契查找(黄金分割法查找)算法
  16. 保姆级讲解Transformer
  17. python简易程序教程_Python-自制简易程序挂机刷御魂
  18. Unity中雾效的开启
  19. 快速搭建Android应用后台服务器
  20. mysql logs_MySQL Logs

热门文章

  1. 为什么Docker,Vagrant和Ansible等工具比以往更热门
  2. 编程开源_立即注册免费的在线开源编程课程
  3. (47)fs创建多级目录
  4. Bootstrap CSS 编码规范之媒体查询的位置
  5. Git笔记(21) 分布式工作流程
  6. matlab 中sumg,MATLAB)课后实验答案[1]
  7. # 电脑管家_如何彻底关闭电脑上的“恶心小广告”?联想电脑管家一步到位!...
  8. vscode比较整个文件夹_vscode开发ROS1(5)-ROS工程目录结构
  9. 【错误】【vscode】'#' not expected here
  10. 各种流行编程语言的优缺点