Bootstrap

单例 C++ 懒汉+恶汉

单例设计模式是一种创建型设计模式,确保一个类只有一个实例,减少了内存的开销,并提供一个全局访问点访问该实例。 私有化构造函数、拷贝构造函数、赋值函数 ,定义一个类的私有静态对象成员,定义一个公共的访问该实例静态对象成员的方法,返回该静态对象成员 ,单例设计模式 有懒汉式:获取该类的对象时才创建该类的实例(局部静态变量解决线程不安全),还有饿汉式:获取前就已经创建好。单例模式一般没有接口,扩展困难。

#include <iostream>
#include <vector>
#include <thread>
#include <queue>
#include <functional>
#include <mutex>
#include <condition_variable>
#include <chrono>
class ThreadPool {
private:
    std::vector<std::thread> threads;
    std::queue<std::function<void()>> tasks;
    std::mutex mutex;
    std::condition_variable condition;
    bool stop;
    ThreadPool() : stop(false) {
        int numThreads = std::thread::hardware_concurrency(); 
 //来获取当前系统支持的并发线程数量,在多线程编程中,可以使用这个值来确定最佳的线程数量以提高程序的性能。
        for (int i = 0; i < numThreads; ++i) {
            threads.emplace_back([this] {
                while (true) {
                    std::unique_lock<std::mutex> lock(mutex);
                    condition.wait(lock, [this] { return stop || !tasks.empty(); });
                    if (stop && tasks.empty()) {
                        return; }
                    std::function<void()> task=std::move(tasks.front());
                    tasks.pop();
               lock.unlock();//确保只有一个线程共享资源,这个资源以及取出来了,就可以解锁让其他线程去访问了
                    task();
                }           });      } }
    ThreadPool(const ThreadPool& theadpool) = delete;
ThreadPool& operator=(const ThreadPool& theadpoll) = delete;
/*MprpcApplication(const MprpcApplication&) = delete;
MprpcApplication(MprpcApplication&&) = delete;
还有这种写法*/
//析构函数是私有的时候,只有类的成员函数才能调用析构函数
    
public: 
~ThreadPool() {
        {
            std::unique_lock<std::mutex> lock(mutex);
            stop = true;
        }
        condition.notify_all();
        for (auto& thread : threads) {
            thread.join();
        }  }

    static ThreadPool& getInstance() {使用引用避免拷贝构造
        //懒汉模式需要解决线程不安全
        //使用C++11的call_once实现线程安全,避免多个线程进来的时候同时new
//多线程运行的结果的单线程运行的结果一样,但是call_once只能在多线程里面使用,在main()里面调用会报错,像主函数thread t1什么的那样的可以
        
        //也使用两个 if 判断语句的技术称为双检锁;好处是,只有判断指针为空的时候才加锁
        //最好的是使用局部静态变量来解决
        static ThreadPool instance; 在 C++11 中,静态局部变量这种方式天然是线程安全的
这里不能定义为引用,引用是引用已经存在的对象
        return instance;
       /*
;饿汉模式,线程安全, 
        */ }
    // 向任务队列中添加任务
    template<typename F, typename... Args>//任意数量,类型的参数
    void enqueue(F&& f, Args&&... args) {可变参数模板
        // 将各种类型的任务包装为std::function,然后加入任务队列,
        std::function<void()> task=std::bind(std::forward<F>(f), std::forward<Args>(args)...);
        {
            std::unique_lock<std::mutex> lock(mutex);
            tasks.emplace(std::move(task));
        }
        condition.notify_one(); // 通知一个等待的线程去执行任务
 }};
int main() {
   // ThreadPool::getInstance(); // 获取线程池实例
    for (int i = 0; i < 8; ++i) {
       ThreadPool::getInstance().enqueue([i] {
std::cout << "Task " << i << " is running in thread  " << std::this_thread::get_id() << std::endl;
            std::this_thread::sleep_for(std::chrono::seconds(5));
            std::cout << "Task " << i << " is done " << std::endl;
            }); }  
return 0;}
饿汉:
class Singleton
	{
	public:
	static Singleton* GetInstance() //通过调用GetInstance() 在类外获得实例
		{	
			return &_slt;                //返回这个实例的地址
		} 
	private:
		static Singleton _slt; //类内声明

;