线程池+日志(纯代码)

thread_pool.h

#pragma once

#include <iostream>
#include <queue>
#include <thread>
#include <functional>
#include <mutex>
#include <vector>
#include <unistd.h>
#include <condition_variable>
#include "task.h"

using namespace std;
using namespace placeholders;

#define numdefault 5

template <class T>
class thread_pool
{
public:
    thread_pool(int num = numdefault)
        : _num(num), _vt(num)
    {

        for (int i = 0; i < _num; i++)
        {

            string name = "thread_";
            name += to_string(i + 1);
            // 移动赋值,线程不支持左值拷贝
            _vt[i] = thread(&thread_pool<T>::task_execution, this, name); // 成员函数默认第一个参数是this指针,所以要显式传参
            // _vt[i] = thread(bind(&thread_pool<T>::task_execution, this,_1), name);//bind可以与function功能一样,不过可以提前确定参数
        }
    }
    void task_execution(const string &args) // 多个线程开始任务执行
    {
        while (1)
        {
            T t;//调用默认构造
            {
                //共享代码段
                unique_lock<mutex> ul(_mtx);
                while (_qt.empty()) // 无任务就等待
                {
                    cond.wait(ul); // 等待期间会解锁,多线程会再等待队列中阻塞,等待成功会上锁
                }
                t = _qt.front();
                _qt.pop();
            }
            // 处理任务
            t();
            cout<<args<<": ";
            t.print_task_finish();
            sleep(1);
        }
    }

    void push(const T &t)//传任务
    {
        unique_lock<mutex> ul(_mtx);
        _qt.push(t);
        cond.notify_one();//有任务则条件满足
    }

    ~thread_pool()//
    {
        for (int i = 0; i < _num; i++) // C++11 使用thread不join的话程序会崩溃
        {
            _vt[i].join();
        }
    }

private:
    int _num;           // 线程数目
    queue<T> _qt;       // 任务管理
    vector<thread> _vt; // 管理线程

    mutex _mtx;              // 锁
    condition_variable cond; // 条件变量,任务为空等待
};

task.h

#pragma once

#include <iostream>
#include"Log.h"
using namespace std;

char operates[] = {'+', '-', '*', '/', '%', '&',  '~', '|', '!', '^'};
class task
{
public:
    task() {} // 需要一个默认的构造函数
    task(int x, int y, char operat)
        : _x(x), _y(y), _operat(operat)
    {
        l.enable(0);//日志在显示器打印
    }

    void operator()()
    {
        switch (_operat)
        {
        case '+':
            _result = _x + _y;
            break;
        case '-':
            _result = _x - _y;
            break;
        case '*':
            _result = _x * _y;
            break;
        case '/':
        {
            if (_y == 0)
            {
                _s = "除数为0";
            }
            else
                _result = _x / _y;
        }
        break;
        case '&':
            _result = _x & _y;
            break;
        case '|':
            _result = _x | _y;
            break;
        case '^':
            _result = _x ^ _y;
            break;
        default:
            _s = "目前未录入该操作";
            break;
        }
    }
    void print_task_finish()
    {
        if (_s.empty())
            cout << _x << _operat << _y << " = " << _result ;
        else
            cout << _s ;

        l.Log_infom(Info,"  ");
        
    }
    void print_task_start()
    {
        cout << _x << _operat << _y << " = ???";
        l.Log_infom(Info,"  ");
    }
    ~task()
    {
    }

private:
    int _x;
    int _y;
    int _result;
    string _s; // 存放错误信息
    char _operat;
};

Log.h

#pragma once
#include <iostream>
#include <time.h>
#include <map>
#include <stdarg.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
using namespace std;

enum // 可以设置日志等级
{
    Debug,
    Info,
    Warning,
    Error,
    Fatal
};
enum//打印方式
{
    Screen,
    onlyfile,
    classifyfile
};
const string logdir="log";//目录文件
class Log
{
public:
    Log()
    {
        levermap[Debug] = "Debug";
        levermap[Info] = "Info";
        levermap[Warning] = "Warning";
        levermap[Error] = "Error";
        levermap[Fatal] = "Fatal";

        mkdir(logdir.c_str(),0777);//创建目录,并在指定目录下打印
    }

    void exchange(string &s, tm *&cur_time)//时间戳转换成标准时间
    {
        s = to_string(cur_time->tm_year + 1900) + '/' + to_string(cur_time->tm_mon) + '/' + to_string(cur_time->tm_mday) + '-' + to_string(cur_time->tm_hour) + ':' + to_string(cur_time->tm_min) + ':' + to_string(cur_time->tm_sec);
    }

    void write_way(const string &filename, const string &loginfo)//文件打印
    {
        int fd = open(filename.c_str(), O_WRONLY | O_APPEND | O_CREAT, 0666);
        if (fd == -1)
            cout << "文件打开失败" << endl;
        write(fd, loginfo.c_str(), loginfo.size());
        close(fd);
    }
    void write_log(int lever, const string &loginfo)//日志写入位置
    {
        string tmp = logdir+'/'+"log.";
        switch (style)
        {
        case 0://显示器打印
            cout << loginfo;
            break;
        case 1://log.txt里打印
            write_way(tmp + "txt", loginfo);
            break;
        case 2://分类到各自对应的文件里打印
            write_way(tmp + levermap[lever], loginfo);
            break;
        default:
            break;
        }
    }

    void enable(int sty)
    {
        style = sty;
    }

    void Log_infom(int lever, const char *format, ...) // 格式formats
    {
        char tmp[1024];
        va_list args;                              // 可变参数部分的起始地址
        va_start(args, format);                    // 初始化,通过format确定可变参数个数
        vsnprintf(tmp, sizeof(tmp), format, args); // 将数据写到tmp中
        va_end(args);                              //

        time_t t = time(nullptr);     // 得到当前的时间戳
        tm *cur_time = localtime(&t); // 传入时间戳
        string s;
        exchange(s, cur_time); // 转换成具体的时间
        string loginfo;
        loginfo = loginfo + tmp + ' ' + '[' + levermap[lever] + ']' + '[' + s + ']' + '\n';

        write_log(lever, loginfo);
    }

    ~Log()
    {
    }

private:
    map<int, string> levermap;
    int style = 0;//默认往显示器中打印
    int lever=Debug;
};
Log l;

test.cpp 

#include"thread_pool.h"
#include<time.h>
#include<cstdlib>

void test_log()
{
    l.enable(0);
    l.Log_infom(Debug,"haha %d,i am %s,what is %f",37,"cr",3.7);
    l.Log_infom(Debug,"haha %d,i am %s,what is %f",37,"cr",3.7);
    l.Log_infom(Debug,"haha %d,i am %s,what is %f",37,"cr",3.7);
    l.Log_infom(Info,"haha %d,i am %s,what is %f",37,"cr",3.7);
    l.Log_infom(Warning,"haha %d,i am %s,what is %f",37,"cr",3.7);
    l.Log_infom(Error,"haha %d,i am %s,what is %f",37,"cr",3.7);
    l.Log_infom(Fatal,"haha %d,i am %s,what is %f",37,"cr",3.7);
}
void publish(const string& name)
{
    thread_pool<task> tp;
    srand(time(nullptr));
    while(1)
    {
        int x=rand()%101;
        int y=rand()%101;
        char operat=operates[rand()%sizeof(operates)];
        task t(x,y,operat);
        cout<<name<<": ";
        t.print_task_start();
        tp.push(t);
        sleep(1);
    }
}
int main()
{
    thread t(publish,"thread_0");
    t.join();//线程等待

    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

CR0712

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值