Browse Source

V0.4.1
1、修改了ThreadPool默认的线程个数
2、修改了OneThread创建线程的方式,可以循环执行,也可以单次执行

Apple 5 months ago
parent
commit
1c8420e436
4 changed files with 117 additions and 40 deletions
  1. 27 0
      common/FmtLog/fmtlog.h
  2. 32 22
      common/OneThread/OneThread.cpp
  3. 43 4
      common/OneThread/OneThread.h
  4. 15 14
      common/ThreadPool/ThreadPool.cpp

+ 27 - 0
common/FmtLog/fmtlog.h

@@ -103,4 +103,31 @@ const std::regex _reg_file(R"(.*/([\S]*[\.][\S]*)$)");
 //     fmt::format(fg(fmt::color::green), "Hello, {}!\n", _log_time);
 // }
 
+/**
+ * @brief 采用单例模式
+ * 
+ */
+// class FmtLog
+// {
+// private:
+//     FmtLog();
+//     FmtLog(const FmtLog &fl) = delete;
+//     FmtLog &operator=(const FmtLog &fl) = delete;
+// public:
+//     ~FmtLog();
+//     static FmtLog& getInstance()
+//     {
+//         static FmtLog fl;
+//         return fl;
+//     }
+
+//     /*  */
+// private:
+//     /* 子线程函数,处理字符串 */
+//     void threadProcessStr();
+
+// private:
+
+// };
+
 #endif /* FMTLOG_H */

+ 32 - 22
common/OneThread/OneThread.cpp

@@ -1,27 +1,37 @@
 #include "OneThread.h"
 #include <QDebug>
-
+#include <QCoreApplication>
 
 OneThread::OneThread(QThread* thread, QObject* parent) : QObject(parent), m_thread(thread)
 {
-    m_timerStartThread.setTimerType(Qt::PreciseTimer);
-    m_timerStartThread.setSingleShot(true);
-
     /* 将自身移动到子线程中去 */
     this->moveToThread(m_thread);
 
-    
 
-    /* 连接信号和槽 */
-    connect(&m_timerStartThread, &QTimer::timeout, this, &OneThread::do_timeoutWork);
-    connect(this, &OneThread::signal_startThread, this, &OneThread::do_timeoutWork);
     /* 指定为队列连接 */
     connect(this, &OneThread::signal_runTask, this, &OneThread::do_runTask,Qt::QueuedConnection);
     /* 注册数据类型 */
     qRegisterMetaType<std::function<int(void)>>("std::function<int(void)>");
     qRegisterMetaType<std::function<void(void)> >("std::function<void(void)>");
+    /* 连接信号和槽 */
+    connect(this, &OneThread::signal_runTask, this, &OneThread::do_runTask);
+    connect(this, &OneThread::signal_runTaskRunOne, this, &OneThread::do_runTaskRunOne);
 }
 
+OneThread::OneThread(QObject* parent) : QObject(parent)
+{
+    m_thread = new QThread();
+    /* 将自身移动到子线程中去 */
+    this->moveToThread(m_thread);
+    /* 指定为队列连接 */
+    connect(this, &OneThread::signal_runTask, this, &OneThread::do_runTask,Qt::QueuedConnection);
+    /* 注册数据类型 */
+    qRegisterMetaType<std::function<int(void)>>("std::function<int(void)>");
+    qRegisterMetaType<std::function<void(void)> >("std::function<void(void)>");
+    /* 连接信号和槽 */
+    connect(this, &OneThread::signal_runTask, this, &OneThread::do_runTask);
+    connect(this, &OneThread::signal_runTaskRunOne, this, &OneThread::do_runTaskRunOne);
+}
 
 OneThread::~OneThread()
 {
@@ -34,26 +44,26 @@ OneThread::~OneThread()
     }
 }
 
-/* 开启线程 */
-void OneThread::startThread()
-{
-    m_timerStartThread.start(0);
-}
-
-/* 线程函数 */
-void OneThread::do_timeoutWork()
-{
-    qDebug() << "----- do_timeoutWork , Thread ID: " << QThread::currentThreadId();
-    // emit signal_runTask(m_func);
-    qDebug() << "----- do_timeoutWork end -----";
-}
 
 /* 传入函数,运行函数 */
 void OneThread::do_runTask(std::function<void(void)> func)
 {
     qDebug() << "----- do_runTask , Thread ID: " << QThread::currentThreadId();
-    func();
+    m_threadRunning = true;
+    while(m_threadRunning)
+    {
+        func();
+        /* 进入事件循环 */
+        QCoreApplication::processEvents();
+        /* 延时1ms */
+        QThread::usleep(100);
+    }
     qDebug() << "----- do_runTask end -----";
 }
 
+void OneThread::do_runTaskRunOne(std::function<void(void)> func)
+{
+    func();
+}
+
 

+ 43 - 4
common/OneThread/OneThread.h

@@ -10,7 +10,19 @@
 /**
  * 这个类提供了一种方便的线程调用方法,可以直接用信号将需要放入新线程
  * 运行的函数传递给这个类,然后就会在槽函数中运行这个函数
+ * 使用方法:
+ *      1. 创建一个OneThread对象,传入一个QThread对象,或者不传入,会自动创建一个QThread对象
+ *      2. 使用addTask或者addTaskRunOne添加任务,addTask会进入循环,addTaskRunOne只会执行一次
+ *      3. 使用bindTask绑定函数和参数,手动触发信号,注意,触发信号前,要先开启子线程getThread()->start();
  * 
+ *  使用示例:
+ *     1、非成员函数 
+ *          void func(int a, int b) { std::cout << a + b << std::endl; }
+ *          thread.add_task(func, 1, 2);
+ *     2、成员函数 
+ *          void A::func(int a, int b) { std::cout << a + b << std::endl; }
+ *          A a;
+ *          thread.add_task(&A::func, &a, 1, 2);
  */
 
 
@@ -19,9 +31,35 @@ class OneThread : public QObject
     Q_OBJECT
 public:
     explicit OneThread(QThread* thread, QObject* parent = nullptr);
+    explicit OneThread(QObject* parent = nullptr);
     ~OneThread();
+    /* 获取子线程 */
+    QThread* getThread() const { return m_thread; }
+    /* 停止子线程 */
+    void stopThread() { m_threadRunning = false; }
 
-    void startThread();
+    /* 添加任务,开启子线程,这个会进入循环,不会退出,调用stopThread会停止线程 */
+    template<typename F, typename... Args>
+    void addTask(F&& f, Args&&... args)
+    {
+        if(!m_thread->isRunning())
+        {
+            m_thread->start();
+        }
+        std::function<void(void)> task = std::bind(std::forward<F>(f), std::forward<Args>(args)...);
+        emit signal_runTask(task);
+    }
+    /* 添加任务,开启子线程,这里只会执行一次 */
+    template<typename F, typename... Args>
+    void addTaskRunOne(F&& f, Args&&... args)
+    {
+        if(!m_thread->isRunning())
+        {
+            m_thread->start();
+        }
+        std::function<void(void)> task = std::bind(std::forward<F>(f), std::forward<Args>(args)...);
+        emit signal_runTaskRunOne(task);
+    }
     /* 将函数与参数绑定 */
     template<typename F, typename... Args>
     std::function<void(void)> bindTask(F&& f, Args&&... args)
@@ -30,16 +68,17 @@ public:
     }
 
 signals:
-    void signal_startThread();
     void signal_runTask(std::function<void(void)> func);
+    void signal_runTaskRunOne(std::function<void(void)> func);
 
 private slots:
-    void do_timeoutWork();
     void do_runTask(std::function<void(void)> func);
+    void do_runTaskRunOne(std::function<void(void)> func);
 
 private:
-    QTimer m_timerStartThread;          /* 开启线程的定时器 */
+    bool m_threadRunning = false;
     QThread* m_thread = nullptr;
+    QTimer m_timer;    /* 定时器 */
 
     std::function<void(void)> m_func;    /* 运行的函数 */
 };

+ 15 - 14
common/ThreadPool/ThreadPool.cpp

@@ -1,8 +1,9 @@
 #include "ThreadPool.h"
 
-#include "spdlog/spdlog.h"
+#include "FmtLog/fmtlog.h"
 #include "fmt/std.h"
 
+
 /**
  * @brief Construct a new Thread Pool:: Thread Pool object
  *        构造函数,从这里创建线程,和Linux C的线程池不同,Linux C的线程池数组管理的是线程ID,
@@ -20,7 +21,7 @@ ThreadPool::ThreadPool() :
     m_threadMiniNum = 3;
     m_threadAddNum = 2;
     m_threadMiniIdle = 2;
-    m_threadMaxIdle = 6;
+    m_threadMaxIdle = 4;
     m_threadRunNum = 0;
     m_threadLiveNum = 0;
     m_threadExitNum = 0;
@@ -28,7 +29,7 @@ ThreadPool::ThreadPool() :
     /* 创建管理线程,this表示是这个类的成员函数 */
     m_managerThread = std::thread(&ThreadPool::managerThread, this);
 
-    SPDLOG_DEBUG("***** Hello ThreadPool *****");
+    FMTLOG_DEBUG("***** Hello ThreadPool *****");
 
     // /* 创建初始的numThread个线程 */
     // createThread(numThread);
@@ -36,14 +37,14 @@ ThreadPool::ThreadPool() :
 /* 析构函数 */
 ThreadPool::~ThreadPool()
 {
-    SPDLOG_INFO("线程池正在退出...");
+    FMTLOG_INFO("线程池正在退出...");
     /* 将stop置为true */
     {
         std::unique_lock<std::mutex> lock(m_mutexTask);
         m_stop = true;
     }
 
-    SPDLOG_INFO("通知所有工作线程退出...");
+    FMTLOG_INFO("通知所有工作线程退出...");
     /* 发送条件变量,通知所有线程 */
     m_cond_Task.notify_all();
     /* 等待所有的线程退出并回收完成 */
@@ -54,10 +55,10 @@ ThreadPool::~ThreadPool()
         std::this_thread::sleep_for(std::chrono::milliseconds(100));
     }
 
-    SPDLOG_INFO("回收管理线程...");
+    FMTLOG_INFO("回收管理线程...");
     /* 先回收管理线程 */
     m_managerThread.join();
-    SPDLOG_INFO("===== 线程池退出完成 =====");
+    FMTLOG_INFO("===== 线程池退出完成 =====");
 }
 
 
@@ -108,7 +109,7 @@ void ThreadPool::worker()
     /* 使用流将线程ID转换成字符串,不然fmt无法打印 */
     std::stringstream ss;
     ss << std::this_thread::get_id();
-    SPDLOG_DEBUG("线程ID:{}退出任务循环", ss.str());
+    FMTLOG_DEBUG("线程ID:{}退出任务循环", ss.str());
 
     return;
 }
@@ -125,7 +126,7 @@ void ThreadPool::managerThread()
         /* 获取空闲线程的个数 */
         int num_idle = m_threadLiveNum.load() - m_threadRunNum.load();
         /* 判断线程是否够用,是否需要创建新的线程 */
-        // SPDLOG_DEBUG("***** 判断是否需要添加线程 *****");
+        // FMTLOG_DEBUG("***** 判断是否需要添加线程 *****");
         if ((num_idle < m_threadMiniIdle.load()) && (m_threadLiveNum.load() < m_threadMaxNum) )
         {
             std::unique_lock<std::mutex> lock(m_mutexTask);
@@ -160,7 +161,7 @@ void ThreadPool::managerThread()
             
             if(numAdd > 0)
             {
-                // SPDLOG_INFO("需要添加{}个线程", numAdd);
+                // FMTLOG_INFO("需要添加{}个线程", numAdd);
                 createThread(numAdd);
                 continue;   /* 直接下一个循环,无需检查需不需要销毁线程 */
             }
@@ -168,7 +169,7 @@ void ThreadPool::managerThread()
         }
 
         /* 判断空闲线程是否过多,是否需要销毁几个线程 */
-        // SPDLOG_DEBUG("***** 判断是否需要销毁线程 *****");
+        // FMTLOG_DEBUG("***** 判断是否需要销毁线程 *****");
         /* 由于没规定每次销毁的线程个数,所以这里使用m_threadAddNum作为每次销毁的标准个数 */
         if (num_idle > m_threadMaxIdle.load())
         {
@@ -179,7 +180,7 @@ void ThreadPool::managerThread()
             }
             m_threadExitNum.exchange(num_Exit);
 
-            SPDLOG_INFO("有{}个线程需要退出", m_threadExitNum.load());
+            FMTLOG_INFO("有{}个线程需要退出", m_threadExitNum.load());
             /* 唤醒需要退出的num_idle个线程 */
             for (int i = 0; i < num_Exit; i++)
             {
@@ -189,10 +190,10 @@ void ThreadPool::managerThread()
         /* 回收退出的线程 */
         clearThread();
 
-        // SPDLOG_INFO("线程池中的线程实例个数:{}", m_threads.size());
+        // FMTLOG_INFO("线程池中的线程实例个数:{}", m_threads.size());
         std::this_thread::sleep_for(std::chrono::seconds(1));
     }
-    SPDLOG_INFO("管理线程退出...");
+    FMTLOG_INFO("管理线程退出...");
 }
 
 /**