C++11手撕线程池 call_once 单例模式 Singleton / condition_variable 与其使用场景

这篇具有很好参考价值的文章主要介绍了C++11手撕线程池 call_once 单例模式 Singleton / condition_variable 与其使用场景。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、call_once 单例模式 Singleton 

大家可以先看这篇文章:https://zh.cppreference.com/w/cpp/thread/call_once

/*
    std::call_once
    void call_once( std::once_flag& flag, Callable&& f, Args&&... args );
*/
#include <iostream>
#include <mutex>
#include <thread>

std::once_flag flag1, flag2;

void simple_do_once() {
    std::call_once(flag1, []() {
        std::cout << "简单样例:调用一次\n";
    });
}

void test1() {
    std::thread st1(simple_do_once);
    std::thread st2(simple_do_once);
    std::thread st3(simple_do_once);
    std::thread st4(simple_do_once);
    st1.join();
    st2.join();
    st3.join();
    st4.join();
}

void may_throw_function(bool do_throw) {
    if (do_throw) {
        std::cout << "抛出:call_once 会重试\n"; // 这会出现不止一次
        throw std::exception();
    }
    std::cout << "没有抛出,call_once 不会再重试\n"; // 保证一次
}

void do_once(bool do_throw) {
    try {
        std::call_once(flag2, may_throw_function, do_throw);
    }
    catch (...) {}
}

void test2() {
    std::thread t1(do_once, true);
    std::thread t2(do_once, true);
    std::thread t3(do_once, false);
    std::thread t4(do_once, true);
    t1.join();
    t2.join();
    t3.join();
    t4.join();
}
int main() {
    test1();
    test2();
    return 0;
}

C++11手撕线程池 call_once 单例模式 Singleton / condition_variable 与其使用场景,线程池,单例模式,call_once,Singleton,手撕线程池,c++11

call_once 应用在单例模式,以及关于单例模式我的往期文章推荐:C++ 设计模式----“对象性能“模式_爱编程的大丙 设计模式-CSDN博客https://heheda.blog.csdn.net/article/details/131466271

懒汉是一开始不会实例化,什么时候用就什么时候new,才会实例化
饿汉在一开始类加载的时候就已经实例化,并且创建单例对象,以后只管用即可
--来自百度文库
#include <iostream>
#include <thread>
#include <mutex>
#include <string>

// 日志类:在整个项目中,有提示信息或者有报错信息,都通过这个类来打印
// 这些信息到日志文件,或者打印到屏幕上。显然,全局只需要一个日志类的
// 对象就可以完成所有的打印操作了。不需要第二个类来操作,这个时候就可以
// 使用单例模式来设计它

std::once_flag onceFlag;
class Log {
public:
    Log(const Log& log) = delete;
    Log& operator=(const Log& log) = delete;
    // static Log& getInstance() { 
    //     static Log log; // 饿汉模式
    //     return log;
    // }
    static Log& getInstance() { // 懒汉模式
        std::call_once(onceFlag, []() {
            std::cout << "简单样例:调用一次\n";
            log = new Log;
        });
        return *log;
    }
    void PrintLog(std::string msg) {
        std::cout << __TIME__ << msg << std::endl;
    }
private:
    Log() {};
    static Log* log; 
};
Log* Log::log = nullptr;

void func() {
    Log::getInstance().PrintLog("这是一个提示");
}

void print_error() {
    Log::getInstance().PrintLog("发现一个错误");
}

void test() {
    std::thread t1(print_error);
    std::thread t2(print_error);
    std::thread t3(func);
    t1.join();
    t2.join();
    t3.join();
}

int main() {
    test();
    return 0;
}

C++11手撕线程池 call_once 单例模式 Singleton / condition_variable 与其使用场景,线程池,单例模式,call_once,Singleton,手撕线程池,c++11

二、condition_variable 与其使用场景

#include <iostream>
#include <mutex>
#include <thread>
#include <condition_variable>
#include <queue>

std::queue<int> queue;
std::condition_variable cond;
std::mutex mtx;

void Producer() {
    for (int i = 0; i < 10; i++) {
        {
            std::unique_lock<std::mutex> locker(mtx);
            queue.push(i);
            cond.notify_one();
            std::cout << "Producer : " << i << std::endl;
        }
        std::this_thread::sleep_for(std::chrono::microseconds(100));
    }
}

void Consumer() {
    while (1) {
        std::unique_lock<std::mutex> locker(mtx);
        cond.wait(locker, []() {
            return !queue.empty();
            });
        int value = queue.front();
        queue.pop();
        std::cout << "Consumer :" << value << std::endl;
    }
}

int main() {
    std::thread t1(Producer);
    std::thread t2(Consumer);
    t1.join();
    t2.join();
    return 0;
}

C++11手撕线程池 call_once 单例模式 Singleton / condition_variable 与其使用场景,线程池,单例模式,call_once,Singleton,手撕线程池,c++11

三、C++11 手撕线程池 + 单例模式(call_once)

  • ThreadPool.h
#include <iostream>
#include <thread>
#include <mutex>
#include <string>
#include <condition_variable>
#include <queue>
#include <vector>
#include <functional>
std::once_flag onceFlag;
class ThreadPool {
private:
    ThreadPool();
public:
    ThreadPool(const ThreadPool& obj) = delete;
    ThreadPool& operator=(const ThreadPool& obj) = delete;
    static ThreadPool& getInstance();
    ~ThreadPool();
    template<class F, class... Args>
    void enqueue(F&& f, Args&&... args) {
        std::function<void()> task =
            std::bind(std::forward<F>(f), std::forward<Args>(args)...);
        {
            std::unique_lock<std::mutex> locker(mtx);
            tasks.emplace(std::move(task));
        }
        cond.notify_one();
    }
    inline void setNum(int num) {
        threadNum = num;
    }
    inline void printNum() {
        std::cout << "线程数量为:" << threadNum << std::endl;
    }
private:
    static ThreadPool* pool;
    std::vector<std::thread> threads;// 线程数组
    std::queue<std::function<void()>> tasks;//任务队列
    std::mutex mtx;// 互斥锁
    std::condition_variable cond;//条件变量
    bool stop;
    int threadNum;// 线程数量
};

  • ThreadPool.cpp
#include "ThreadPool.h"
#include <iostream>
ThreadPool* ThreadPool::pool = nullptr;
ThreadPool::ThreadPool() {
    stop = false;
    threadNum = 4;
    for (int i = 0; i < threadNum; ++i) {
        threads.emplace_back([this]() {
            while (1) {
                std::unique_lock<std::mutex> locker(mtx);
                cond.wait(locker, [this]() {
                    return !tasks.empty() || stop;
                    });
                if (stop && tasks.empty()) {
                    return;
                }
                std::function<void()> task(std::move(tasks.front()));
                tasks.pop();
                task();// 执行这个任务
            }
            });
    }
}

ThreadPool::~ThreadPool() {
    {
        std::unique_lock<std::mutex> locker(mtx);
        stop = true;
    }
    cond.notify_all();
    for (auto& t : threads) {
        t.join();
    }
}

ThreadPool& ThreadPool::getInstance() { // 懒汉模式
    std::call_once(onceFlag, []() {
        std::cout << "懒汉模式:调用一次" << std::endl;
        pool = new ThreadPool();
        });
    return *pool;
}
  •  main.cpp
#include <iostream>
#include "ThreadPool.h"
#include <thread>
void addTask() {
    ThreadPool& pool = ThreadPool::getInstance();
    pool.setNum(8);
    for (int i = 0; i < 10; ++i) {
        pool.enqueue([i]() {
            std::cout << "task : " << i << " is runing!" << std::endl;
            std::this_thread::sleep_for(std::chrono::microseconds(10));
            std::cout << "task : " << i << " is done!" << std::endl;
            });
    }
}

void test() {
    std::thread t1(addTask);
    std::thread t2(addTask);
    std::thread t3(addTask);
    t1.join();
    t2.join();
    t3.join();
}

int main() {
    test();
    return 0;
}

运行结果:

懒汉模式:调用一次
task : 0 is runing!
task : 0 is done!
task : 0 is runing!
task : 0 is done!
task : 1 is runing!
task : 1 is done!
task : 0 is runing!
task : 0 is done!
task : 1 is runing!
task : 1 is done!
task : 1 is runing!
task : 1 is done!
task : 2 is runing!
task : 2 is done!
task : 3 is runing!
task : 3 is done!
task : 2 is runing!
task : 2 is done!
task : 4 is runing!
task : 4 is done!
task : 3 is runing!
task : 3 is done!
task : 2 is runing!
task : 2 is done!
task : 3 is runing!
task : 3 is done!
task : 4 is runing!
task : 4 is done!
task : 5 is runing!
task : 5 is done!
task : 4 is runing!
task : 4 is done!
task : 5 is runing!
task : 5 is done!
task : 6 is runing!
task : 6 is done!
task : 7 is runing!
task : 7 is done!
task : 8 is runing!
task : 8 is done!
task : 9 is runing!
task : 9 is done!
task : 6 is runing!
task : 6 is done!
task : 7 is runing!
task : 7 is done!
task : 5 is runing!
task : 5 is done!
task : 6 is runing!
task : 6 is done!
task : 8 is runing!
task : 8 is done!
task : 9 is runing!
task : 9 is done!
task : 7 is runing!
task : 7 is done!
task : 8 is runing!
task : 8 is done!
task : 9 is runing!

D:\Work\vsproject\c++11\x64\Debug\c++11.exe (进程 32636)已退出,代码为 0。
要在调试停止时自动关闭控制台,请启用“工具”->“选项”->“调试”->“调试停止时自动关闭控制台”。
按任意键关闭此窗口. . .
  • 关于智能指针的回顾,可以看我的往期文章了解一下喔!

独占指针:unique_ptr 与 函数调用 笔记-CSDN博客https://heheda.blog.csdn.net/article/details/135841140计数指针:shared_ptr (共享指针)与函数 笔记-CSDN博客https://heheda.blog.csdn.net/article/details/135851596shared_ptr 与 unique_ptr 的转换 笔记-CSDN博客https://heheda.blog.csdn.net/article/details/135853468weak_ptr 与 一个难发现的错误(循环依赖问题)笔记-CSDN博客https://heheda.blog.csdn.net/article/details/135854106文章来源地址https://www.toymoban.com/news/detail-818483.html

到了这里,关于C++11手撕线程池 call_once 单例模式 Singleton / condition_variable 与其使用场景的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 单例模式(Singleton)

    单例是一种创建型设计模式,让你能够保证一个类只有一个实例,并提供一个访问该实例的全局节点。 1. 问题 单例模式同时解决了两个问题,所以违反了单一职责原则: 保证一个类只有一个实例 。 为该实例提供一个全局访问节点 。 为什么会有人想要控制一个类所拥有的实

    2024年02月11日
    浏览(35)
  • 单例模式(Singleton)

    单例模式 保证一个类仅有一个实例 ,并 提供一个全局访问点来访问它 ,这个类称为单例类。可见,在实现单例模式时,除了保证一个类只能创建一个实例外,还需提供一个全局访问点。 为提供一个全局访问点,可以使用全局变量,但全局变量无法禁止用户实例化多个对象

    2024年02月14日
    浏览(38)
  • 10-单例模式(Singleton)

    保证一个类只有一个实例,并提供一个访问它的全局访问点 优点:安全且在多线程情况下保持高性能。 描述:这种方式能达到双检锁方式一样的功效,但实现更简单。对静态域使用延迟初始化,应使用这种方式而不是双检锁方式。这种方式只适用于静态域的情况,双检锁方

    2024年02月03日
    浏览(46)
  • 设计模式四:单例模式(Singleton)

    单例模式,是一种常用的软件设计模式。在它的核心结构中只包含一个被称为单例的特殊类。 通过单例模式可以保证系统中,应用该模式的类一个类只有一个实例。即一个类只有一个对象实例。 单例模式是设计模式中最简单的形式之一。这一模式的目的是使得类的一个对象

    2024年02月15日
    浏览(46)
  • 单例模式(Singleton Pattern)

    单例模式(Singleton Pattern)是结构最简单的设计模式,它的 核心结构中只包含一个被称为单例类的特殊类 。通过 单例模式可以确保系统中一个类只有一个实例 ,且该实例易于被外界访问,从而方便对实例个数的控制并节约系统资源。 如何确保一个类只有一个实例并且这个实

    2024年02月03日
    浏览(64)
  • 单例模式(Singleton Pattern)

    单例模式(Singleton Pattern)是一种创建型设计模式,用于确保一个类只有一个实例,并提供全局访问点来获取该实例。 单例模式的特点是: 只允许类创建一个实例。 提供一个全局访问点来获取该实例。 对外部代码隐藏实例化过程,使得外部代码无法直接创建实例。 以下是一

    2024年02月15日
    浏览(35)
  • java设计模式-单例模式(Singleton)

    单例模式(Singleton)就是一个类只能有一个实例,自行实例化,并向系统提供这一实例,这个类就是单例类。单例模式的特点: 一个类只能有一个实例; 单例类自己实例化; 单例类给其它对象提供这个单一实例。 资源管理类经常被设计为单例模式,例如管理属性文件的类。

    2024年02月15日
    浏览(39)
  • C++ 中的单例模式singleton

    在面向对象编程中,设计模式是解决常见问题的最佳实践。单例模式是其中之一,它确保一个类只有一个实例,并提供一个全局访问点来获取该实例。在本文中,我们将详细介绍 C++ 中的单例模式。 单例模式是一种设计模式,它限制一个类只能创建一个对象。这个模式通常用

    2024年02月21日
    浏览(44)
  • 大话设计模式——9.单例模式(Singleton Pattern)

    简介 确保一个类只有一个实例,并提供全局访问点来获取该实例,是最简单的设计模式。 UML图: 单例模式共有两种创建方式: 饿汉式(线程安全) 提前创建实例,好处在于该实例全局唯一,不存在线程冲突;坏处在于未使用时也会占用内存资源。 懒汉式(原生写法存在线

    2024年04月12日
    浏览(49)
  • 《游戏编程模式》学习笔记(六)单例模式 Singleton Pattern

    保证一个类只有一个实例,并且提供了访问该实例的全局访问点。 定义这种东西一般都是不说人话的,要想要理解这句话的意思,我们得把它揉开了才能搞明白。 我们先看前半句 “保证一个类只有一个实例”,单例一般使用类来实现,也就是说,这个单例类,其有且只能有

    2024年02月12日
    浏览(44)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包