Linux|多线程(三)
线程池
线程池是一种多线程处理形式,处理过程中它将被提交的任务分配给预先创建好的多个线程中的一个去执行。
线程池的实现
#pragma once
#include <pthread.h>
#include <vector>
#include <string>
#include <unistd.h>
#include <pthread.h>
#include <queue>
#include <functional>
#include "task.hpp"
#include "thread.hpp"
using namespace ThreadModel;
// void test(const std::string &name)
// {// while (1)
// {
// std::cout << name << "is running.." << std::endl;
// sleep(1);
// }
// }
const int Default_nums = 3;template <class T>
class ThreadPool
{using func_t = std::function<void(const std::string name)>;private:bool isEmpty(){return _task_queue.size() == 0;}void Sleep(){pthread_cond_wait(&_cond, &_mutex);}void lockQueue(){pthread_mutex_lock(&_mutex);}void wakeUp(){pthread_cond_signal(&_cond);}void wakeUpAll(){pthread_cond_broadcast(&_cond);}void unlockQueue(){pthread_mutex_unlock(&_mutex);}void hadertask(const std::string name){lockQueue();while (true){while (isEmpty() && _isrunning){_sleepnums++;std::cout << name << " star sleep" << std::endl;Sleep();std::cout << name << " awaken" << std::endl;_sleepnums--;}if (isEmpty() && !_isrunning){unlockQueue();std::cout << name << " quit" << std::endl;break;}T t = _task_queue.front();_task_queue.pop();unlockQueue();t();std::cout << t.solve() << std::endl;}}void init(){// 并将调用func时的第一个参数传递给hander函数。func_t func = std::bind(&ThreadPool::hadertask, this, std::placeholders::_1);for (int i = 0; i < _thread_nums; i++){std::string name = "thread-" + std::to_string(i + 1);_threads.emplace_back(name, func);std::cout << name << " init sucess" << std::endl;}}ThreadPool(int thread_nums = Default_nums) : _thread_nums(thread_nums), _sleepnums(0){init();pthread_mutex_init(&_mutex, nullptr);pthread_cond_init(&_cond, nullptr);}public:~ThreadPool(){pthread_cond_destroy(&_cond);pthread_mutex_destroy(&_mutex);}static ThreadPool<T> * GetInstance(int thread_nums = Default_nums){if (_tp == nullptr){pthread_mutex_lock(&_sig_mutx);if (_tp == nullptr){_tp = new ThreadPool(thread_nums);std::cout<<"create instance"<<std::endl;}pthread_mutex_unlock(&_sig_mutx);}std::cout<<"get instance"<<std::endl;return _tp;}void start(){_isrunning = true;std::cout << "threadpool is running:" << std::endl;for (auto &thread : _threads) // 这个引用特别重要// 如果不传引用 thread 出了函数会被销毁 访问name 会出问题{thread.start();}}void equeue(const T &in){// 拿数据和放数据要加锁 因为可能脏读lockQueue();if (_isrunning){_task_queue.push(in);if (_sleepnums > 0){wakeUp();}}std::cout << in.inquiry() << std::endl;unlockQueue();}void stop(){wakeUpAll();std::cout << "threadpool stop" << std::endl;_isrunning = false;}private:std::queue<T> _task_queue;int _thread_nums;std::vector<Thread> _threads;bool _isrunning;int _sleepnums;pthread_mutex_t _mutex;pthread_cond_t _cond;static ThreadPool *_tp;static pthread_mutex_t _sig_mutx;
};
template <class T>
ThreadPool<T> *ThreadPool<T>::_tp = nullptr;template <class T>
pthread_mutex_t ThreadPool<T>::_sig_mutx = PTHREAD_MUTEX_INITIALIZER;
日志类
#pragma once
#include <iostream>
#include <string>
#include <unistd.h>
#include <sys/types.h>
#include <ctime>
#include <stdarg.h>
#include <fstream>
#include <cstring>
#include <pthread.h>
#include "lockerguard.hpp"
// namespace{}
namespace log_ns
{
#define SCREEN_TYPE 1
#define FILE_TYPE 2pthread_mutex_t gmutex = PTHREAD_MUTEX_INITIALIZER;enum level{DEBUG = 1,INFO,WARNNING,ERROR,FATAL};std::string levelToString(int level){switch (level){case DEBUG:return "DEBUG";case INFO:return "INFO";case WARNNING:return "WARNNING";case ERROR:return "ERROR";case FATAL:return "FATAL";default:return "UNKNOW";}}std::string GetCurTime(){time_t now = time(nullptr);struct tm *cur_time = localtime(&now);char buff[128];snprintf(buff, 128, "%d-%02d-%02d %02d:%02d:%02d",cur_time->tm_year + 1900,cur_time->tm_mon + 1,cur_time->tm_mday,cur_time->tm_hour,cur_time->tm_min,cur_time->tm_sec);return buff;}class LogMessage{public:std::string _level; // 日志等级pid_t _id; // 进程号std::string _filename; // 文件名int _filenumber; // 行号std::string _cur_time; // 日志所写时间std::string _message_info; // 日志信息};const char *gfile = "./log.txt";class Log{public:Log(const std::string &logfile = gfile) : _logFile(logfile), _type(SCREEN_TYPE){}void FlushLogToScreen(const LogMessage &lg){printf("[%s][%d][%s][%d][%s] %s",lg._level.c_str(),lg._id,lg._filename.c_str(),lg._filenumber,lg._cur_time.c_str(),lg._message_info.c_str());}void FlushLogToFile(const LogMessage &lg){//std::ofstream out(_logFile, std::ios::app);if (!out.is_open())return;char buff[1024];snprintf(buff, sizeof(buff), "[%s][%d][%s][%d][%s] %s",lg._level.c_str(),lg._id,lg._filename.c_str(),lg._filenumber,lg._cur_time.c_str(),lg._message_info.c_str());out.write(buff, strlen(buff));out.close();}void FlushLog(const LogMessage &lg){LockGuard lockguard(&gmutex);switch (_type){case SCREEN_TYPE:FlushLogToScreen(lg);break;case FILE_TYPE:FlushLogToFile(lg);break;default:break;}}void logMessage(int level, std::string filename, int filenumber, const char *format...){LogMessage lg;lg._level = levelToString(level);lg._filename = filename;lg._filenumber = filenumber;lg._cur_time = GetCurTime();lg._id = getpid();va_list ap;va_start(ap, format);char buff[128];vsnprintf(buff, sizeof(buff), format, ap);va_end(ap);FlushLog(lg);}private:int _type;std::string _logFile;};Log lg;
#define LOG(Level, Format, ...) \do \{ \lg.logMessage(Level, __FILE__, __LINE__, Format, ##__VA_ARGS__); \} while (0)
#define EnableScreen() \do \{ \lg.Enable(SCREEN_TYPE); \} while (0)
#define EnableFile() \do \{ \lg.Enable(FILE_TYPE); \} while (0)
}
单例模式
static ThreadPool<T> * GetInstance(int thread_nums = Default_nums){if (_tp == nullptr){pthread_mutex_lock(&_sig_mutx);if (_tp == nullptr){_tp = new ThreadPool(thread_nums);std::cout<<"create instance"<<std::endl;}pthread_mutex_unlock(&_sig_mutx);}std::cout<<"get instance"<<std::endl;return _tp;}
相关文章:
Linux|多线程(三)
线程池 线程池是一种多线程处理形式,处理过程中它将被提交的任务分配给预先创建好的多个线程中的一个去执行。 线程池的实现 #pragma once #include <pthread.h> #include <vector> #include <string> #include <unistd.h> #include <…...
智能合约中如何返回mapping
在 Solidity 中,直接返回一个 mapping 的所有数据是不可能的,因为 mapping 本身不支持直接遍历。但是,可以使用一些技巧来实现这一目标,例如通过维护一个额外的数组来跟踪 mapping 中的键,并通过这个数组来返回所有的键…...
nginx的学习(二):负载均衡和动静分离
简介 nginx的负载均衡和动静分离的简单使用 负载均衡配置 外部访问linux的ip地址:80/edu/a.html地址,会轮询访问Tomcat8080和Tomcat8081服务。 Tomcat的准备 准备两个Tomcat,具体准备步骤在nginx的学习一的反向代理例子2中,在Tomcat8080…...
普中51单片机:DS1302时钟芯片讲解与应用(十)
文章目录 引言基本特性什么是RAM?什么是涓流充电? 电路图和引脚说明通信协议以及工作流程寄存器控制寄存器日历/时钟寄存器 DS1302读写时序代码演示——数码管显示时分秒 引言 DS1302 是一款广泛使用的实时时钟 (RTC) 芯片,具有低功耗、内置…...
Preact:轻量级替代React的选择
Preact是一个轻量级的JavaScript库,它提供了与React相似的API,但体积更小,性能更优。Preact的核心理念是尽可能地保持与React的兼容性,同时去除不必要的部分,使其成为一个理想的替代品,尤其是在对性能和包大…...
全栈嵌入式C++、STM32、Modbus、FreeRTOS和MQTT协议:工业物联网(IIoT)可视化系统设计思路(附部分代码解析)
项目概述 随着工业4.0时代的到来,工业物联网(IIoT)在提高生产效率、降低运营成本和实现智能制造方面得到了广泛应用。本项目旨在开发一个全面的工业物联网监控系统,能够实时监测设备的温度、压力、振动和电流等参数,并…...
Greenplum数据库中的数据倾斜问题及处理方法
一、数据倾斜问题的原因 数据分布不均匀:当数据在表的分区或分片中不均匀分布时,会导致某些分区或分片的数据量较大,从而引发数据倾斜问题。连接键存在热点数据:如果连接操作中使用的键值存在热点数据,即某些键值出现…...
缓存设计理论
缓存设计理论是一个涉及多个方面的复杂主题,主要目标是优化数据访问速度,减少数据访问延迟,提高系统性能,并同时保持数据的一致性和系统的稳定性。以下是从几个关键方面对缓存设计理论的概述: 一、缓存的作用与目的 …...
IDEA-安装插件 驼峰下划线转换
第一步:安装 file-settings-plugins-在marketplace搜索“CamelCase”-点击安装 第二步:设置 file-settings-editor-camel_case 第三步:使用 选中想转换的遍历 使用快捷键 Alt Shift U...
乾坤: 微前端项目切换时样式闪动(从无样式变为正常样式需要等 css chunk 文件加载完成, 加载延时受网速影响)
背景: 点击基座项目页面左侧目录, 进入微前端子项目页面, 会有短暂的样式未加载效果一闪而过, 造成页面闪烁或更严重的其他样式错位问题 定位: 同事查了 qiankun git 项目的 issue: https://github.com/umijs/qiankun/issues/219 , 找到解决方案 解决: 项目 webpack 打包配…...
《电子元器件之固态电容》
固态电容全称是固态铝质电解电容,它与普通液态铝质电解电容的最大差别在于采用了不同的介电材料。液态铝电容介电材料为电解液,而固态电容的介电材料是固态的导电性高分子材料。 固态电容和液态电容,从外观上区分,就是固态电容顶…...
PLC 远程下载网关
一、 产品概述 SSF-BOX-100 是三石峰科技有限公司推出的工业级 PLC 远程下载网关,主 要用于 PLC 远程调试、程序上下载,为用户提供一种简单可靠的远程维护方案。 1.1 SGBOX 软件 SGBOX 软件是 SSF-BOX-100 网关的配套软件,可以查看设备状态…...
【Django】 读取excel文件并在前端以网页形式显示-安装使用Pandas
文章目录 安装pandas写views写urls安装openpyxl重新调试 安装pandas Pandas是一个基于NumPy的Python数据分析库,可以从各种文件格式如CSV、JSON、SQL、Excel等导入数据,并支持多种数据运算操作,如归并、再成形、选择等。 更换pip源 pip co…...
自动控制:带死区的PID控制算法
带死区的PID控制算法 在计算机控制系统中,为了避免控制动作过于频繁,消除因频繁动作所引起的振荡,可采用带死区的PID控制。带死区的PID控制通过引入一个死区,使得在误差较小的范围内不进行控制动作,从而减少控制系统的…...
橙单后端项目下载编译遇到的问题与解决
今天下载orange-admin项目,不过下载下来运行出现一些问题。 1、涉及到XMLStreamException的几个类都出现下面的错误 The package javax.xml.stream is accessible from more than one module: <unnamed>, java.xml ctrl-shift-t 可以找到这个引入是哪些包里…...
EasyExcel 初使用—— Java 实现多种写入 Excel 功能
前言 大家好,我是雪荷。之前有一篇博客(EasyExcel 初使用—— Java 实现读取 Excel 功能_java easyexcel.read-CSDN博客)介绍了 Java 如何读取 Excel 表格,那么此篇博客就和大家介绍下 Java 如何利用 EasyExcel 写入 Excel。 Ea…...
MySQL 和 SQL Server 中的连表更新 UPDATE JOIN 写法比较
MySQL 和 SQL Server 中的连表更新 UPDATE JOIN 写法比较 一、前言1. MySQL 写法1.1 解释 2. SQL Server 写法2.1 解释 二、总结 一、前言 在关系型数据库管理系统(RDBMS)中,使用 UPDATE 语句进行表格更新是非常常见的操作。特别是当需要根据…...
手把手教你FL Studio 24.1.1.4234中文破解安装激活图文激活教程
在数字化音乐制作的浪潮中,FL Studio 24.1.1.4234中文破解版的发布无疑又掀起了一股新的热潮。这款由Image-Line公司开发的数字音频工作站(DAW)软件,以其强大的功能和易用的界面,赢得了全球无数音乐制作人的青睐。本文…...
使用Spring Boot与Spire.Doc实现Word文档的多样化操作
博客主页: 南来_北往 系列专栏:Spring Boot实战 前言 使用Spring Boot与Spire.Doc实现Word文档的多样化操作具有以下优势: 强大的功能组合:Spring Boot提供了快速构建独立和生产级的Spring应用程序的能力,而Spire.Doc则…...
从食堂采购系统源码到成品:打造供应链采购管理平台实战详解
本篇文章,笔者将详细介绍如何从食堂采购系统的源码开始,逐步打造一个完备的供应链采购管理平台,帮助企业实现采购流程的智能化和高效化。 一、需求分析与规划 一般来说,食堂采购系统需要具备以下基本功能: 1.供应商…...
【力扣数据库知识手册笔记】索引
索引 索引的优缺点 优点1. 通过创建唯一性索引,可以保证数据库表中每一行数据的唯一性。2. 可以加快数据的检索速度(创建索引的主要原因)。3. 可以加速表和表之间的连接,实现数据的参考完整性。4. 可以在查询过程中,…...
【Web 进阶篇】优雅的接口设计:统一响应、全局异常处理与参数校验
系列回顾: 在上一篇中,我们成功地为应用集成了数据库,并使用 Spring Data JPA 实现了基本的 CRUD API。我们的应用现在能“记忆”数据了!但是,如果你仔细审视那些 API,会发现它们还很“粗糙”:有…...
HTML前端开发:JavaScript 常用事件详解
作为前端开发的核心,JavaScript 事件是用户与网页交互的基础。以下是常见事件的详细说明和用法示例: 1. onclick - 点击事件 当元素被单击时触发(左键点击) button.onclick function() {alert("按钮被点击了!&…...
Java线上CPU飙高问题排查全指南
一、引言 在Java应用的线上运行环境中,CPU飙高是一个常见且棘手的性能问题。当系统出现CPU飙高时,通常会导致应用响应缓慢,甚至服务不可用,严重影响用户体验和业务运行。因此,掌握一套科学有效的CPU飙高问题排查方法&…...
【7色560页】职场可视化逻辑图高级数据分析PPT模版
7种色调职场工作汇报PPT,橙蓝、黑红、红蓝、蓝橙灰、浅蓝、浅绿、深蓝七种色调模版 【7色560页】职场可视化逻辑图高级数据分析PPT模版:职场可视化逻辑图分析PPT模版https://pan.quark.cn/s/78aeabbd92d1...
MFC 抛体运动模拟:常见问题解决与界面美化
在 MFC 中开发抛体运动模拟程序时,我们常遇到 轨迹残留、无效刷新、视觉单调、物理逻辑瑕疵 等问题。本文将针对这些痛点,详细解析原因并提供解决方案,同时兼顾界面美化,让模拟效果更专业、更高效。 问题一:历史轨迹与小球残影残留 现象 小球运动后,历史位置的 “残影”…...
关于uniapp展示PDF的解决方案
在 UniApp 的 H5 环境中使用 pdf-vue3 组件可以实现完整的 PDF 预览功能。以下是详细实现步骤和注意事项: 一、安装依赖 安装 pdf-vue3 和 PDF.js 核心库: npm install pdf-vue3 pdfjs-dist二、基本使用示例 <template><view class"con…...
stm32wle5 lpuart DMA数据不接收
配置波特率9600时,需要使用外部低速晶振...
Appium下载安装配置保姆教程(图文详解)
目录 一、Appium软件介绍 1.特点 2.工作原理 3.应用场景 二、环境准备 安装 Node.js 安装 Appium 安装 JDK 安装 Android SDK 安装Python及依赖包 三、安装教程 1.Node.js安装 1.1.下载Node 1.2.安装程序 1.3.配置npm仓储和缓存 1.4. 配置环境 1.5.测试Node.j…...
【多线程初阶】单例模式 指令重排序问题
文章目录 1.单例模式1)饿汉模式2)懒汉模式①.单线程版本②.多线程版本 2.分析单例模式里的线程安全问题1)饿汉模式2)懒汉模式懒汉模式是如何出现线程安全问题的 3.解决问题进一步优化加锁导致的执行效率优化预防内存可见性问题 4.解决指令重排序问题 1.单例模式 单例模式确保某…...
