当前位置: 首页 > news >正文

为何要打印日志?C++在高并发下如何写日志文件(附源码)?

为何要打印日志?让程序裸奔不是一件很快乐的事么?

有些BUG就像薛定谔的猫,具有波粒二象性,当你试图去观察它时它就消失了,当你不去观察它时,它又会出现。当你在测试人员面前赌咒发誓,亲自路演把程序跑一遍的时候,这些bug就会神奇的消失;一旦离开你的骚操作重新回到测试人员手中,这些bug又会突然的出现。这就是开发人员和测试人员互相对天发誓自证清白的尬聊场面。
因为这些幽灵Bug破坏了团队的氛围,伤害了开发和测试人员的感情,从而导致了产品质量下降。 因此非常有必要找到这些bug发生的原因。

试图找到这些具备量子特性的bug发生的原因,通常的手段就是打印日志,因为你很难通过几次思想实验或几次尬聊就能自证清白。

打印日志是查找、分析、定位问题的一个非常有效的手段。尤其对后台程序而言更加重要,后台程序需要长期运行,运行期间会面临各种各样的情况,这些情况包括正常业务逻辑,非正常业务逻辑,甚至是异常情况。我们往往需要在不同情况下将这些发生的事情按时间轴记录下来,从而在系统出现问题或瓶颈时进行回溯分析。

Java中有现成的日志打印类log4j,并将日志定义了4个级别:ERROR、WARN、INFO、DEBUG。通常级别越高输出的日志越少,如果你的后台程序一天就能输出一个G的ERROR日志,那也是非常不容易的事,基本可以告别程序员生涯了,还打啥日志啊?
还能让测试人员愉快的工作么?
通常在出现ERROR日志时,我们就需要定位问题,这就需要打印大量的DEBUG或INFO日志来进行问题回溯。这篇文章不是介绍Java如何打印日志,网络上的文章已经很多了。
这里说一下C++在高并发下如何打印日志,这里实现最基本功能(仅做抛砖引玉之用)。通常我们会写一个日志输出函数,如下:

void Logout(const char* pszLogFile, const char* pszLog)
{// 参数检查assert(pszLogFile);assert(pszLog);if(NULL == pszLogFile || NULL == pszLog)return;// 打开日志文件FILE* pFile = fopen(pszLogFile, "ab+");if(pFile){// 写日志fwrite((void*)pszLog, 1, strlen(pszLog), pFile);fclose(pFile);}
}

如果是不同级别的日志,可以定义不同日志文件名,你也可以丰富上面的日志函数,增加发生的时间、所在线程ID、所在文件名等辅助信息。

通常情况下这种方式没有问题,通过一次文件IO操作将信息记录下来。但如果是一个后台服务,当高并发发生的时候,问题就会出现了。此时将会有多个线程同时写日志的情况发生,尤其是那些INFO类型的日志,比如记录HTTP请求的request信息,这时你的日志将会成为系统的瓶颈。毕竟大量的文件IO操作也是一种负担,这些IO操作可能要超过你的正常业务逻辑,比如写数据库、网络IO等。

此时我们需要将日志先写入内存块中,当内存写满后在一次性Flush到磁盘中,这样就避免了大量的磁盘IO操作。下面是CFileMem封装类,很简单,里面注释的很详细就不解释了。

头文件.h


#include <windows.h>	// for CRITICAL_SECTION// 缺省内存块大小,大于该值时进行将缓存数据写入磁盘文件
#define SIZE_DEFAULT_MEM	(1024*64)		// 64Kclass CFileMem  
{
public:CFileMem();virtual ~CFileMem();public:// 打开内存文件,dwMemBlockSize为缓存块大小,大于该值时进行一次IO操作BOOL Open(const char* pszPathFile, DWORD dwMemBlockSize = SIZE_DEFAULT_MEM);/*写数据到内存文件,dwFileSize将返回当前磁盘文件的大小,该值可用于外部判断日志文件是否过大,比如当dwFileSize大于多少M时,可重命名文件从而避免单个日志文件过大*/BOOL Write(const char* pszLog, DWORD& dwFileSize);BOOL Write(const unsigned char* pData, DWORD dwDataSize, DWORD& dwFileSize);// 将内存数据写入磁盘BOOL Flush(DWORD& dwFileSize);// 关闭内存文件void Close();// 重命名文件void Rename(const char* pszOldPathFile, const char* pszNewPathFile);protected:CRITICAL_SECTION m_csMem;		// 内存池锁char  m_szPathFile[256];		// 日志文件路径名char* m_pMemBlock;				// 内存块,用于存储文件数据DWORD m_dwMemBlockSize;			// 内存块大小DWORD m_dwPos;					// 内存块的当前位置
};

实现文件.cpp

#include "FileMem.h"
#include <stdio.h>CFileMem::CFileMem()
{m_pMemBlock = NULL;m_dwMemBlockSize = 0;m_dwPos = 0;memset(m_szPathFile, 0, 256);::InitializeCriticalSection(&m_csMem);
}CFileMem::~CFileMem()
{Close();::DeleteCriticalSection(&m_csMem);
}// 打开内存文件,dwMemBlockSize为缓存块大小,大于该值时进行一次IO操作
BOOL CFileMem::Open(const char* pszPathFile, DWORD dwMemBlockSize)
{if(!pszPathFile)return FALSE;// 关闭之前已打开内存块Close();// 保存日志文件全路径名strcpy(m_szPathFile, pszPathFile);if(dwMemBlockSize <= 0)return FALSE;m_pMemBlock = (char*)malloc(dwMemBlockSize);if(NULL == m_pMemBlock)return FALSE;memset(m_pMemBlock, 0, dwMemBlockSize);m_dwMemBlockSize = dwMemBlockSize;m_dwPos = 0;return TRUE;
}/*写数据到内存文件,dwFileSize将返回当前磁盘文件的大小,该值可用于外部判断日志文件是否过大,比如当dwFileSize大于多少M时,可重命名文件从而避免单个日志文件过大
*/
BOOL CFileMem::Write(const char* pszLog, DWORD& dwFileSize)
{return Write((const unsigned char*)pszLog, strlen(pszLog), dwFileSize);
}
BOOL CFileMem::Write(const unsigned char* pData, DWORD dwDataSize, DWORD& dwFileSize)
{dwFileSize = 0;if(NULL == pData || 0 == dwDataSize)return FALSE;// 如果内部没有开辟缓冲区,则直接写文件if(NULL == m_pMemBlock || 0 == m_dwMemBlockSize){FILE* pFile = ::fopen(m_szPathFile, "ab+");if(NULL == pFile)return FALSE;::fwrite(pData, 1, dwDataSize, pFile);// 获取磁盘文件大小::fseek(pFile, 0L, SEEK_END); dwFileSize = ::ftell(pFile);::fclose(pFile);return TRUE;}::EnterCriticalSection(&m_csMem);// 如果内存块已满,则写入磁盘文件DWORD dwTotalSize = m_dwPos + dwDataSize;if(dwTotalSize >= m_dwMemBlockSize){FILE* pFile = ::fopen(m_szPathFile, "ab+");if(NULL == pFile){
::LeaveCriticalSection(&m_csMem);return FALSE;}// 将当前内存中数据写入文件::fwrite(m_pMemBlock, 1, m_dwPos, pFile);::fwrite(pData, 1, dwDataSize, pFile);// 获取磁盘文件大小::fseek(pFile, 0L, SEEK_END); dwFileSize = ::ftell(pFile);::fclose(pFile);// 清空内存块memset(m_pMemBlock, 0, m_dwMemBlockSize);m_dwPos = 0;}else{// 如果内存未满,将当前数据写入内存memcpy(m_pMemBlock+m_dwPos, pData, dwDataSize);m_dwPos += dwDataSize;}
::LeaveCriticalSection(&m_csMem);return TRUE;
}// 将缓冲区的内容写入磁盘
BOOL CFileMem::Flush(DWORD& dwFileSize)
{// 参数dwFileSize = 0;if(NULL == m_pMemBlock || 0 == m_dwMemBlockSize || 0 == m_dwPos)return TRUE;::EnterCriticalSection(&m_csMem);FILE* pFile = ::fopen(m_szPathFile, "ab+");if(NULL == pFile){
::LeaveCriticalSection(&m_csMem);return FALSE;}// 内存数据写入磁盘文件::fwrite(m_pMemBlock, 1, m_dwPos, pFile);// 获取磁盘文件大小::fseek(pFile, 0L, SEEK_END); dwFileSize = ::ftell(pFile);::fclose(pFile);// 清空内存块memset(m_pMemBlock, 0, m_dwMemBlockSize);m_dwPos = 0;::LeaveCriticalSection(&m_csMem);return TRUE;
}void CFileMem::Close()
{// 将内存中文件写入磁盘DWORD dwFileSize = 0;Flush(dwFileSize);// 释放内存块free(m_pMemBlock);m_pMemBlock = NULL;m_dwMemBlockSize = 0;m_dwPos = 0;memset(m_szPathFile, 0, 256);
}// 重命名文件
void CFileMem::Rename(const char* pszOldPathFile, const char* pszNewPathFile)
{
::EnterCriticalSection(&m_csMem);::rename(pszOldPathFile, pszNewPathFile);
::LeaveCriticalSection(&m_csMem);
}

测试函数:

#include <assert.h>
#include <stdio.h>
#include <time.h>	// for Clock
// 传统的日志输出函数
void Logout(const char* pszLogFile, const char* pszLog)
{// 参数检查assert(pszLogFile);assert(pszLog);if(NULL == pszLogFile || NULL == pszLog)return;// 打开日志文件FILE* pFile = fopen(pszLogFile, "ab+");if(pFile){// 写日志fwrite((void*)pszLog, 1, strlen(pszLog), pFile);fclose(pFile);}
}static void TestFileMem()
{const char* pszLogFile1 = "c:/test1.log";const char* pszLogInfo = "Hello world\r\n";int iCount  = 10000;	// 循环写日志1万次// 第一种方式:传统写日志方式clock_t cStart = clock();for(int i = 0; i < iCount; i++)Logout(pszLogFile1, pszLogInfo);clock_t cEnd = clock();long lElapsed = cEnd - cStart;printf("Logout Elpased time %d ms\r\n", lElapsed);// 第二种方式:使用CFileMem写日志const char* pszLogFile2 = "c:/test2.log";CFileMem fm;DWORD dwFileSize = 0;fm.Open(pszLogFile2);cStart = clock();for(i = 0; i < iCount; i++)fm.Write(pszLogInfo, dwFileSize);fm.Close();cEnd = clock();lElapsed = cEnd - cStart;printf("CFileMem Elpased time %d ms\r\n", lElapsed);}

输出结果

在这里插入图片描述
通过测试比较,第二种方式速度更加快速,而且是线程安全的。
我写的“HttpServer:一款Windows平台下基于IOCP模型的高并发轻量级web服务器”,就使用该类进行日志打印,效果不错。

感谢您的阅读!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.exyb.cn/news/show-35490.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈,一经查实,立即删除!

java获取TDengine链接错误:java.lang.NoSuchMethodError: setNumOfCols#4320

java根据本地tdengine驱动获取链接报错误java.lang.NoSuchMethodError: setNumOfCols#4320&#xff0c;网上查了一下是驱动版本不兼容还是怎么着&#xff0c;反正目前更换了许多个版本的依赖没有解决&#xff0c;我目前获取链接的方法是官网上给的rest方式&#xff1a; public…...

新概念英语(第四册,旧版)复习(原文及全文翻译)——Lesson 51 - Training Elephants(训象)

Lesson 51 - Training Elephants Two main techniques have been used for training elephants, which we may call respectively the tough and the gentle. The former method simply consists of setting an elephant to work and beating him until he does what is expe...

element时间选择器 选择当前时间和之后的时间

<el-form-item label"称号有效期&#xff1a;" prop"featureEndTime"><el-date-pickerv-model"formObj.featureEndTime"type"datetime"placeholder"选择日期"format"yyyy-MM-dd HH:mm:ss"value-format&q…...

2021.8.23

写项目 画创建群的界面和查看好友资料界面 重新修改了一下好友列表的布局&#xff0c;增加显示查看好友资料&#xff0c;删除好友的按钮&#xff0c;还没有改好。。。。。。。。。。。。。。。 思考怎么实现表情包的发送...

HTML内置对象

目录 前言&#xff1a; 一、基本对象Object: 二、内置对象之Array&#xff1a; 三、内置对象之Math&#xff1a; 四、内置对象之Number&#xff1a; 五、内置对象之String&#xff1a; 六、内置对象之Date&#xff1a; 七、内置对象之JSON&#xff08;ES5新增内置对象&am…...

Nocas单机启动命令

之前在Linux中单机启动Nocas使用命令&#xff1a;sh startup.sh -m standalone 但是在cmd窗口使用该命令不行&#xff0c;因为sh命令是在Linux系统中的文件&#xff1b; 而在本机cmd窗口运行Nocas&#xff0c;输入命令startup.cmd -m standalone...

淘宝商品详情接口

有需要联系QQ&#xff1a;1195918027 简要描述 根据商品id获取详情数据 请求URL http://xxx.xxx.xxx.xxx:xxxx/taobao.shop.info 请求方式 get 请求参数 参数名必选类型说明itemid是string商品idtoken是string权限token 返回示例 {"api": "wdetail"…...

从青铜到王者的路线,6年菜鸟开发面试字节跳动Android研发岗,移动架构师成长路线

前言 今天我给大家再次分享一下&#xff0c;我最近的一些读书的感想&#xff0c;思考起来&#xff0c;确实能够给自己带来一些真实的帮助和启发&#xff0c;希望大家在平时的工作学习中&#xff0c;也能够认清楚学习的一些本质。 如果我们的学习是在不断掌握应对具体工作场景…...

vue--CompositionAPI 中如何使用 VueX

a.同步方法改变数据&#xff1a; Home.vue <template><div class"home"><img alt"Vue logo" src"../assets/logo.png"><h1>{{name}}</h1></div> </template><script> import {toRefs} from v…...

html标签字符,在thymeleaf中非转义显示

html标签字符&#xff0c;在thymeleaf中非转义显示 对于“非转义文本”使用 th:utext th:utext"${lastAnnouncement.content}"th:text和 th:utext效果对比&#xff1a; <p><strong>This is my textarea to be replaced with CKEditor 4.</strong&g…...

在vue3中vue-router的使用

从vue2转到使用vue3&#xff0c;遇到了好多问题&#xff0c;原来使用的方法有很大不同。 1.安装vue-routernext npm install vue-routernext --save 2.创建名为“router”的文件夹&#xff0c;在创建index.js 3.编写index.js 首先引入vue-router插件&#xff0c;然后创建一个…...

js面向对象 —— 继承

二、继承 ES6之前并没有给我们提供extends继承。我们可以通过 构造函数原型对象 模拟实现继承,被称为组合继承。 2.1 、call() 调用这个函数并且修改函数运行时的this指向 ● thisArg :当前调用函数this的指向对象 ● arg1 , arg2 :传递的其他参数 2.2、借用构造函数继承父…...

Java List remove时报UnsupportedOperationException

遇到的问题&#xff1a; 解决后&#xff1a; 源代码&#xff1a; /*** 需求&#xff1a;删除字符串中的a8&#xff0c;并重新组成字符串* param args*/public static void main(String[] args) {String str "a3,a4,a5,a6,a8";String[] moIds str.split(StringPool.…...

计算结构体的大小

#include <stdio.h> struct mystruct1 { // 1字节对齐 4字节对齐 int a; // 4 4 char b; // 1 2(11) short c; // 2 2 }; int main(void)…...

DDD领域驱动设计学习笔记

...

ResultMap 关系映射详细使用

关于MyBatis中ResultMap的详细使用ResultMap简介使用ResultMap创建sql 模仿一对多或多对一关系创建数据库创建SpringBoot项目 导入mybatis依赖pojo---------------------------------------------------------------------------------StudentTeacherdao----------------------…...

Nacos心跳时间配置及服务快速上下线

Nacos心跳时间配置及服务快速上下线 Nacos默认心跳时间是30秒&#xff0c;不太满足正式环境需要&#xff0c;需要调整心跳时间更短&#xff0c;让线上服务上下线能快速感知. 1.修改微服务的nacos的心跳配置时间 preserved.heart.beat.interval: 1000 #该实例在客户端上报心跳…...

SpringBoot知识点总结

目录 1、SpringBoot简介及其优点 2、如何重新加载SpringBoot上的更改&#xff0c;而无需重新启动服务器&#xff1f; 3.SpringBoot中的监视器是什么以及如何监视 4.如何在SpringBoot中禁用Actuator端点安全性&#xff1f; 5.如何在自定义端口上运行SpringBoot应用程序&…...

SQL server安装时显示重启计算机失败问题解决办法

SQL server安装时显示重启计算机失败问题解决办法参考文章&#xff1a; &#xff08;1&#xff09;SQL server安装时显示重启计算机失败问题解决办法 &#xff08;2&#xff09;https://www.cnblogs.com/netflix/p/12074481.html 备忘一下。...

Linux系统编程系列(一)

系统软件属于系统的底层&#xff0c;与内核和系统核心库直接进行交互&#xff0c;系统编程则是进行系统软件的关键&#xff0c;熟悉系统编程可以重现如shell、vim、gcc等系统软件。而作为一个高级C/C编程人员&#xff0c;往往需要在底层进行多次调用&#xff0c;学习Linux系统编…...

为什么template必须有且只能有一个div呢?

单文件组件   当我们在vue-cli脚手架搭建的vue开发环境下使用单文件组件时&#xff0c;一般会这么写&#xff1a; <template><div class"box">这里是页面内容</div> </template>如果我们尝试在template标签下写两个div&#xff0c;那么编…...

数据结构---二叉线索树

数据结构—二叉线索树 原理&#xff1a;参考趣学数据结构 代码&#xff1a; #include<stdio.h> #include<stdlib.h> typedef struct bmTree {int data;struct bmTree* lchild, *rchild;int ltag, rtag; }bmTree; bmTree * preNULL;//中序遍历的前驱指针 void cr…...

使用RAK7268网关与RAK3172节点连接至TTN最新的服务器TTS上

一、背景 当需要连接网关到TTN的时候我们突然发现&#xff1a;在TTN V2版本上已经无法创建新的网关了。另外&#xff0c;V2版本对于当前已创建的网关支持在今年年底也要失效了。所以&#xff0c;我们需要了解如何将网关连接到TTN最新的服务器TTS上。 二、目的 本文将会使用到RA…...

Xshell无法连接,centos7 network.service 网络服务无法启动或启动自动关闭

在虚拟中下载安装mysql之后&#xff0c;对NetworkManager进行操作&#xff0c;导致与Network服务可能起了冲突&#xff0c;使得导致network.service启动自动关闭&#xff0c;Xshell对虚拟机无法进行链接。 需要对NetworkManager进行调整 # 停止 NetworkManager 系统服务 syste…...

求一款能够批量采集新浪微博相册图片的软件,适合电脑小白使用

新浪微博是我们生活中非常常见的一款社交软件&#xff0c;我们常常会在这上面获取到很多当下热门的信息&#xff0c;大家还会在上面分享自己的日常&#xff0c;很多明星都会使用的一个平台&#xff0c;那如果我们想要下载保存某一个喜欢的博主、明星的相册图片&#xff0c;要怎…...

【JS011】ES6的学习笔记之原始数据类型Symbol

日期&#xff1a;2021年8月23日 作者&#xff1a;Commas 注释&#xff1a;如果您觉得有所帮助&#xff0c;帮忙点个赞&#xff0c;也可以关注我&#xff0c;我们一起成长&#xff1b;如果有不对的地方&#xff0c;还望各位大佬不吝赐教&#xff0c;谢谢^ - ^ (ง •_•)ง 积跬…...

VMware 仅主机模式虚拟机无法 ping 通物理机的问题

前言 最近做了另外一个项目&#xff0c;用的数据库软件版本比较新&#xff0c;我本机装的旧的&#xff0c;因版本原因无法还原数据库&#xff0c;考虑到以最快速度部署开发环境&#xff0c;决定在虚拟机里安装新版数据库软件&#xff0c;使用 VMware 网络类型的仅主机模式&…...

Seurat学习:如何将自定义的聚类标签添加到Seurat对象当中

假如要添加k-means聚类标签&#xff1a; objectmeta.data$k.means.clusters <- k.means.result 绘制自定义标签的UMAP图&#xff1a; DimPlot(object , reduction‘umap’,group.by “k.means.clusters”) 同时显示自定义标签和UMAP图和Seurat中louvain聚类的UMAP图 plot…...

Spring框架的入门知识点

一、概念 1.一款轻量级的JAVAEE解决方案&#xff0c;众多优秀设计模式的组合&#xff1b; 2.作用&#xff08;目的&#xff09;&#xff1a;解耦合&#xff0c;目的是为了解决企业级应用开发的业务逻辑层和其他各层的耦合问题。 3. Spring 的核心思想是&#xff1a; IOC:控制…...

【数据库系统概论(王珊)】第4章——数据库安全性

1、安全性级别 TCSEC将系统划分为四组&#xff08;ABCD&#xff09;七个等级&#xff0c;依次是D、C1、C2、B1、B2、B3、A1。 D级&#xff1a;是最低级别。将一切不符合更高标准的系统均归于D组。如DOS实操作系统中安全标准为D级的典型例子。 C1级&#xff1a;非…...

第十二周报告四

* (程序头部注释开始) * 程序的版权和版本声明部分 * Copyright (c) 2011, 烟台大学计算机学院学生 * All rights reserved. * 文件名称&#xff1a; * 作者&#xff1a;吴瑕 * 完成日期&#xff1a; 2012年 05月 08日 * 版本号&#xff1a; *对任务及求解方法的描述部…...

十三周报告二

(程序头部注释开始) * 程序的版权和版本声明部分 * Copyright (c) 2011, 烟台大学计算机学院学生 * All rights reserved. * 文件名称&#xff1a; * 作者&#xff1a;吴瑕 * 完成日期&#xff1a; 2012年 05月 13日 * 版本号&#xff1a; *对任务及求解方法的描述部分…...

萌宠过春节成消费新热点 广西宠物寄养一“窝”难求

中新社柳州1月31日电 题&#xff1a;萌宠过春节成消费新热点 广西宠物寄养一“窝”难求 作者 林馨 钟建珊1月8日&#xff0c;广西南宁一室内动物观赏乐园内&#xff0c;饲养员与动物亲密互动。中新社记者 俞靖 摄 “新的一年&#xff0c;希望猫狗双全。”时下&#xff0c;“猫…...

SDNU OJ 1182 奖学金

先来贴一个地址&#xff1a;http://www.acmicpc.sdnu.edu.cn/problem/show/1182 题目名字已列在标题上。下面贴一下原题&#xff1a; 描述&#xff1a; 某小学最近得到了一笔赞助&#xff0c;打算拿出其中一部分为学习成绩优秀的前5名学生发奖学金。期末&#xff0c;每个学生…...

管理系统UI

开源框架引用&#xff1a; 1.jquery/jquery-ui 2.bootstrap 3.效果图 4.index.html代码 1 <!DOCTYPE html>2 <html lang"zh-CN">3 <head>4 <meta name"viewport" content"widthdevice-width, initial-scale1.0">5 …...

Atitit 风控之道 attilax著 风险控制 1. 融资风险控制 3 1.1. 风险控制基本知识 3 2. 第8 章 项目风险的分类管理 156 4 2.1. 8.1 项目风险分类 156 4

Atitit 风控之道 attilax著 风险控制1. 融资风险控制 3 1.1. 风险控制基本知识 3 2. 第8 章 项目风险的分类管理 156 4 2.1. 8.1 项目风险分类 156 4 2.2. 8.2 政策与环境风险管理 157 4 2.3. 8.3 管理风险的管理 158 4 2.4. 8.4 进度风险管理 159 4 2.5. 8.5 财务风险管理 164…...

十二周报告一

/* (程序头部注释开始) * 程序的版权和版本声明部分 * Copyright (c) 2011, 烟台大学计算机学院学生 * All rights reserved.* 文件名称&#xff1a;通过撞错理解访问限定符和继承方式 * 作 者&#xff1a; 吴瑕 * 完成日期&#xff1a;2012 年5月 08日 * 版 本 …...

十五周报告二

(程序头部注释开始) * 程序的版权和版本声明部分 * Copyright (c) 2011, 烟台大学计算机学院学生 * All rights reserved. * 文件名称&#xff1a; * 作者&#xff1a;吴瑕 * 完成日期&#xff1a; 2012年 05月 28日 * 版本号&#xff1a; *对任务及求解方法的描述部分…...

少儿编程 电子学会图形化编程等级考试Scratch一级真题解析(选择题)2022年9月

2022年9月scratch一级真题解析 选择题(共25题,每题2分,共50分) 1、点击绿旗,下列哪个选项可以实现播放马叫声并在声音全部播放完后,马向右移动 A、 B、 C、 D、...

马士兵-郑金维—并发编程—1.线程基础概念

一、基础概念 1.1 进程与线程 什么是进程? 进程是指运行中的程序。 比如我们使用钉钉,浏览器,需要启动这个程序,操作系统会给这个程序分配一定的资源(占用内存资源)。 什么线程? 线程是CPU调度的基本单位,每个线程执行的都是某一个进程的代码的某个片段。 举个栗…...

听说你想做一个汽车软件工程师?(下)

在这个系列的第一篇文章 木城&#xff1a;听说你想做一个汽车软件工程师&#xff1f;&#xff08;上&#xff09;里&#xff0c;我们讨论了汽车软件工程师都有哪些职位。但是&#xff0c;就算是同样一个职位&#xff0c;比如“诊断工程师”吧&#xff01;你给ADAS系统做诊断&am…...

九联UNT413A_S905L3A__AI语音_默认打开ADB_完美线刷固件包【可救砖】

UNT413A_S905L3A__AI语音_默认打开ADB_完美线刷固件包【可救砖】_基于云南原机制作_端口5555 固件特点&#xff1a; 1、修改dns&#xff0c;三网通用&#xff1b; 2、开放原厂固件屏蔽的市场安装和u盘安装apk&#xff1b; 3、无开机广告&#xff0c;无系统更新&#xff0c;…...

微商类公众号该如何做市场调研及定位分析

目录 微商公众号市场调研 1. 分析文章的主题、目标用户、解决了用户的哪些需求、阅读数量、点赞数量等 2. 定位相关话题&#xff0c;列表分析可以输出问题的大致数量、阅读数量、回答数量等 3.通过上面的调查&#xff0c;请写出你的定位在整个市场上面的位置&#xff08;包…...

产品经理(09)#用户需求调研

目录 用户需求调研 问卷调研【不用】 用户反馈渠道 用户反馈 通用定理&#xff08;中型产品以上适用&#xff09; 行业数据分析 数据平台 需求验证标准 自有产品数据分析 自有数据之session数据分析 行为分析报告模板 详细分析加例如 过20%就是大需求&#xff1b;…...

行业调研与需求分析方法

行业调研与需求分析方法一、资料获取第三方咨询公司&#xff08;调研报告&#xff09;——宏观看行业市场的发展趋势供给方&#xff08;方案、产品、技术、技术参数等&#xff09;——从平台看行业的需求需求方&#xff08;功能、技术、技术参数等&#xff09;——从行业看对平…...

关于用户调研

关于用户调研 By wangxuntian http://www.wangxuntian.com/?p1912 今天说用户调研&#xff0c;行研、问卷&#xff0c;不谈内容&#xff0c;只谈心得。 一、行业调研 内容多来源于第三方研究报告&#xff0c;国内有CNNIC、艾瑞、DCCI&#xff0c;国外可以查alexa和comsc…...

用户调研怎么做?

第一、产品调研 1.识别和理解目标用户是开始产品设计的第一步&#xff0c;同样重要的是分析市场上类似的产品&#xff0c;分析类似产品针对的用户群&#xff0c;甄别其是否是竞争对手&#xff0c;这些工作对于设计将非常有借鉴意义。理解其他产品的过程有利于比较和理解自己产…...

Microolap DAC for MySQL驱动程序或其他库

Microolap DAC for MySQL驱动程序或其他库 用于MySQL和Delphi/CBuilder(也称为MySQLDAC)的Microolap直接访问组件是一组Borland Delphi/CBuilder组件&#xff0c;允许直接连接到MySQL数据库服务器。DAC for MySQL允许您创建Delphi/CBuilder应用程序&#xff0c;无需BDE、ODBC或…...

在线社交网络(Online Social Networks,OSNs)

在线社交网络&#xff08;Online Social Networks&#xff0c;OSNs&#xff09;简介 随着移动互联网以及移动终端的飞速发展&#xff0c;类型各异的在线社交网络迅速普及。社交网络的出现&#xff0c;极大的丰富了用户的社交需求。不同于传统的信息媒体&#xff0c;在社交网络…...

uni-app入门:全局数据共享方案之mobx

1.全局数据共享介绍 2.准备工作 3.使用说明 3.1 page页面进行全局数据共享 3.2 component组件进行全局数据共享 1.全局数据共享介绍全局数据共享也叫作状态管理,主要用于组件间数据共享问题的处理.实际开发中常用的实现方案:vuex、redux、mobx&…...