c++并发编程实战_并发编程第14篇,并发队列框架实战操作

并发队列框架实战操作

用户态与内核态之间的区别

内核态(Kernel Mode):运行操作系统程序,操作硬件Cpu的调度分配、内存、IO操作。

用户态(User Mode):运行用户程序

0a34391a85b66caa685e71ed5d8a268a.png

Synchronized升级重量锁优化过程

Synchronized 锁 默认是为轻量锁,慢慢升级为重量级锁,当如果线程没有获取锁的时候

会被阻塞等待,同时释放cpu执行权,而我们阻塞或者唤醒线程的过程是有系统内核实现的,所以如果Synchronized 升级为重量锁的时候是一个用户态切换为内核态过程,效率非常低。

异步打印日志的需求

在高并发的情况下,服务器端频繁的接收到请求,这时候因为打印日志本身操作是需要对IO做写的操作,写的操作操作有可能会暂停到打印日志的线程。

用户空间需要切换到内核空间,会导致用户空间阻塞的。

异步日志框架源码分析

 AsyncAppender中AsyncAppenderBase类, 创建了一个Worker线程异步的从队列中获取日志,并且异步写入到硬盘中。

8281b5bcfef680ac2c3cb805842737f8.png

6f1ca6e2843e5640f420a08c128d977c.png

基于ArrayBlockingQueue手写异步框架

public class LogBlockingQueue {private static final int maxCapacity = 20000;private static ArrayBlockingQueuelogBlockingQueue =new ArrayBlockingQueue(maxCapacity);/**
     *
添加log
     *
     * @param
log* @return*/public static boolean addLog(String log) {return logBlockingQueue.offer(log);
    }/**
     *
查询log
     *
     * @param* @return*/
public static String getLog() {return logBlockingQueue.poll();
    }
}
/**
 *
异步写日志文件*/public class LogException {private static final String path = "e://code/abc.log";public static void writeErrorMsg(String content) {writeErrorMsg(path, content);
    }/**
     * @param
path* @throws IOException
     * @
将错误信息输入到txt*/public static void writeErrorMsg(String path, String content) {
        File F = new File(path);//如果文件不存在,就动态创建文件if (!F.exists()) {try {
                F.createNewFile();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        FileWriter fw = null;
        String writeDate = "时间:" + getNowDate() + "---" + "error:" + content;try {//设置为:True,表示写入的时候追加数据fw = new FileWriter(F, true);//回车并换行fw.write(writeDate + "\r\n");
        } catch (IOException e) {
            e.printStackTrace();
        } finally {if (fw != null) {try {
                    fw.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }/**
     * @return* @
获取系统当前时间*/public static String getNowDate() {
        Calendar D = Calendar.getInstance();int year = 0;int moth = 0;int day = 0;
        year = D.get(Calendar.YEAR);
        moth = D.get(Calendar.MONTH) + 1;
        day = D.get(Calendar.DAY_OF_MONTH);
        String nowDate = String.valueOf(year) + "-" + String.valueOf(moth) + "-" + String.valueOf(day);return nowDate;
    }public static void main(String[] args) {writeErrorMsg("abc");
    }
}
@Component
@Slf4jpublic class LogMonitor {public void start() {log.info("开启异步采集日志,存储到硬盘中..");new Worker().start();
    }class Worker extends Thread {@Overridepublic void run() {for (; ; ) {
                String mtLog = LogBlockingQueue.getLog();if (!StringUtils.isEmpty(mtLog)) {
                    LogException.writeErrorMsg(mtLog);log.info("异步的将mtLog:{},写入到银盘中.", mtLog);
                }
            }
        }
    }
}
@Slf4j
@Componentpublic class StartListener implements ApplicationListener {@Autowiredprivate LogMonitor logMonitor;@Overridepublic void onApplicationEvent(ApplicationReadyEvent event) {log.info(">>项目启动成功<<);logMonitor.start();
    }
}

并发编程课程总结

 如何优化多线程

  1. 锁建议做好使用CAS或者自旋锁 ,不建议为悲观锁

  2. Synchronized锁使用偏向锁或者轻量锁 减少锁持有时间

  3. 降低锁的粒度采用 分段锁

  4. 使用fork jojn 并行提高多线程的效率

  5. 减少多线程上下文的切换 使用多核处理器或者是线程池

本章主要说并发队列都运用,并发队列加netty还能做消息中间件,那么并发队列都底层又是怎么实现都呢?

每一行代码都有它的涵义,多问一句为什么;别怕,理清思路,一切代码都是数据的流动和转化,耐心一点,慢慢积累!一起加油!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值