【Linux】:封装线程

打印 上一主题 下一主题

主题 972|帖子 972|积分 2916

朋友们、伙计们,我们又见面了,本期来给大家带来封装线程相关的知识点,如果看完之后对你有一定的启发,那么请留下你的三连,祝大家心想事成!
  
  C 语 言 专 栏:C语言:从入门到醒目
  数据结构专栏:数据结构
  个  人  主  页 :stackY、
  C + + 专 栏   :C++
  Linux 专 栏  :Linux
  
​ 

目录

弁言:
1. 基础框架 
1.1 初步Start接口
1.2 修正后的Start接口
2. Join接口
 2.1 初步测试
3. 添加模版
4. 全部代码


弁言:

   我们想要通过封装原生线程库的方式来实现一个雷同于C++11里面的线程库,这里只是为了来更沉入的学习原生线程库,实现一些基础的功能即可;
    我们创建一个mian.cc文件用于测试线程逻辑;
  Thread.hpp紧张用于封装线程;
  Makefile紧张实现主动化代码构建。
  

  1. 基础框架 

   

  • 我们想要封装的线程需要有对应的线程id、线程名、该线程是否运行以及线程所要执行的任务;
  • 线程所需要执行的任务我们需要用函数包装器(functional)
  • 我们想要实现的方法有一个让线程启动起来的方法,还需要有一个等待线程的方法;
  • 后面根据需要添加对应的成员和方法。
  Thread.hpp:
  
先将基础框架搭建出来,后面再慢慢补充所需要的接口以及代码。
  1.1 初步Start接口

   在Start接口就是用来启动线程,那么在接口设计中就需要先创建进程,在对应的线程执行方法中执行我们预先设计好的func;
  

  

    这里就需要留意一下线程封装时的细节,我们先来看一下创建线程的接口具体传递的参数:
  

  我们设置的线程执行方法函数的参数只有一个参数,但是由于我们自己设置的ThreadRoutine函数是类内函数,那么类内函数会默认自己带一个this指针,以是这于原始函数设计接口不符,以是我们需要将该函数设置为静态成员函数,然后我们将this指针传递给他,然后通过this指针来调用我们预设的func;
  1.2 修正后的Start接口

   

  2. Join接口

   在实现Join之前我们可以设置一个检察线程是否运行的接口以及获取线程名的接口,方便后面的测试;
  在等待线程这里我们直接利用原生线程库的接口:
  

  我们目前不关心等待的效果;
  

   2.1 初步测试

   上面的代码算是一份非常简朴的线程封装代码,那么接下来我们利用main.cc来利用一下我们封装的线程库,由于我们将线程对象化了,以是我们就可以用容器来生存我们的线程,这其实就是一种“先描述,再构造”的过程。
  1. #include <iostream>
  2. #include <unistd.h>
  3. #include <string>
  4. #include <vector>
  5. #include "Thread.hpp"
  6. // 设置线程名
  7. std::string GetThreadName()
  8. {
  9.     static int num = 1;
  10.     char buffer[64];
  11.     snprintf(buffer, sizeof(buffer), "Thread-%d", num++);
  12.     return buffer;
  13. }
  14. void Print()
  15. {
  16.     while(1)
  17.     {
  18.         std::cout << "hello thread" << std::endl;
  19.         sleep(1);
  20.     }
  21. }
  22. int main()
  23. {
  24.     std::vector<Thread> threads;
  25.     int num = 5;
  26.     // 创建
  27.     for(int i = 0; i< num; i++)
  28.     {
  29.         threads.push_back(Thread(GetThreadName(),Print));
  30.     }
  31.     for (auto &t : threads)
  32.     {
  33.         std::cout << t.ThreadName() << ", is running: " << t.IsRunning() << std::endl;
  34.     }
  35.     // 启动
  36.     for (auto &t : threads)
  37.     {
  38.         t.Start();
  39.     }
  40.     for (auto &t : threads)
  41.     {
  42.         std::cout << t.ThreadName() << ", is running: " << t.IsRunning() << std::endl;
  43.     }
  44.     // Join
  45.     for (auto &t : threads)
  46.     {
  47.         t.Join();
  48.     }
  49.     return 0;
  50. }
复制代码

  3. 添加模版

   我们想给我们的线程传递参数,以是我们需要添加模版;
  整体代码:
  1. #pragma once
  2. #include <iostream>
  3. #include <string>
  4. #include <functional>
  5. #include <pthread.h>
  6. template <class T>
  7. using func_t = std::function<void(T)>; // 任务
  8. template <class T>
  9. class Thread
  10. {
  11. public:
  12.     Thread(const std::string &threadname, func_t<T> func, T data)
  13.         : _tid(0), _thread_name(threadname), _isrunning(false), _func(func), _data(data)
  14.     {
  15.     }
  16.     // 执行方法
  17.     static void* ThreadRoutine(void *args)
  18.     {
  19.         Thread *ts = static_cast<Thread *>(args);
  20.         ts->_func(ts->_data);
  21.         return nullptr;
  22.     }
  23.     // 启动
  24.     bool Start()
  25.     {
  26.         int n = pthread_create(&_tid, nullptr, ThreadRoutine, this); // 将this指针传递给ThreadRoutine
  27.         if(n == 0)
  28.         {
  29.             _isrunning = true;
  30.             return true;
  31.         }
  32.         else return false;
  33.     }
  34.     // 等待
  35.     bool Join()
  36.     {
  37.         if (!_isrunning)
  38.             return false;
  39.         int n = pthread_join(_tid, nullptr);
  40.         if (n == 0)
  41.         {
  42.             return true;
  43.         }
  44.         return false;
  45.     }
  46.     bool IsRunning()
  47.     {
  48.         return _isrunning;
  49.     }
  50.     std::string ThreadName()
  51.     {
  52.         return _thread_name;
  53.     }
  54.     ~Thread() {}
  55. private:
  56.     pthread_t _tid;           // 线程id
  57.     std::string _thread_name; // 线程名
  58.     bool _isrunning;          // 线程是否运行
  59.     func_t<T> _func;             // 线程所执行任务
  60.     T _data;                   // 传递数据类型
  61. };
复制代码

  4. 全部代码

   Makefile
  1. thread:main.cc
  2.         g++ -o $@ $^ -std=c++11 -lpthread
  3. .PHONY:clean
  4. clean:
  5.         rm -f thread
复制代码
main.cc
  1. #include <iostream>
  2. #include <unistd.h>
  3. #include <string>
  4. #include <vector>
  5. #include "Thread.hpp"
  6. // 设置线程名
  7. std::string GetThreadName()
  8. {
  9.     static int num = 1;
  10.     char buffer[64];
  11.     snprintf(buffer, sizeof(buffer), "Thread-%d", num++);
  12.     return buffer;
  13. }
  14. void Print(int num)
  15. {
  16.     while(num--)
  17.     {
  18.         std::cout << "hello thread num :" << num << std::endl;
  19.         sleep(1);
  20.     }
  21. }
  22. int main()
  23. {
  24.     Thread<int> t(GetThreadName(), Print, 5);
  25.     t.Start();
  26.     t.Join();
  27.     // std::vector<Thread> threads;
  28.     // int num = 5;
  29.     // // 创建
  30.     // for(int i = 0; i< num; i++)
  31.     // {
  32.     //     threads.push_back(Thread(GetThreadName(),Print));
  33.     // }
  34.     // for (auto &t : threads)
  35.     // {
  36.     //     std::cout << t.ThreadName() << ", is running: " << t.IsRunning() << std::endl;
  37.     // }
  38.     // // 启动
  39.     // for (auto &t : threads)
  40.     // {
  41.     //     t.Start();
  42.     // }
  43.     // for (auto &t : threads)
  44.     // {
  45.     //     std::cout << t.ThreadName() << ", is running: " << t.IsRunning() << std::endl;
  46.     // }
  47.     // // Join
  48.     // for (auto &t : threads)
  49.     // {
  50.     //     t.Join();
  51.     // }
  52.     // Thread ts(Printf, GetThreadName());
  53.     // std::cout << "is thread running? " << ts.IsRunning() << std::endl;
  54.     // ts.Start();
  55.     // std::cout << "is thread running? " << ts.IsRunning() << std::endl;
  56.     // ts.Join();
  57.     return 0;
  58. }
复制代码
Thread.hpp
  1. #pragma once
  2. #include <iostream>
  3. #include <string>
  4. #include <functional>
  5. #include <pthread.h>
  6. template <class T>
  7. using func_t = std::function<void(T)>; // 任务
  8. template <class T>
  9. class Thread
  10. {
  11. public:
  12.     Thread(const std::string &threadname, func_t<T> func, T data)
  13.         : _tid(0), _thread_name(threadname), _isrunning(false), _func(func), _data(data)
  14.     {
  15.     }
  16.     // 执行方法
  17.     static void* ThreadRoutine(void *args)
  18.     {
  19.         Thread *ts = static_cast<Thread *>(args);
  20.         ts->_func(ts->_data);
  21.         return nullptr;
  22.     }
  23.     // 启动
  24.     bool Start()
  25.     {
  26.         int n = pthread_create(&_tid, nullptr, ThreadRoutine, this); // 将this指针传递给ThreadRoutine
  27.         if(n == 0)
  28.         {
  29.             _isrunning = true;
  30.             return true;
  31.         }
  32.         else return false;
  33.     }
  34.     // 等待
  35.     bool Join()
  36.     {
  37.         if (!_isrunning)
  38.             return false;
  39.         int n = pthread_join(_tid, nullptr);
  40.         if (n == 0)
  41.         {
  42.             return true;
  43.         }
  44.         return false;
  45.     }
  46.     bool IsRunning()
  47.     {
  48.         return _isrunning;
  49.     }
  50.     std::string ThreadName()
  51.     {
  52.         return _thread_name;
  53.     }
  54.     ~Thread() {}
  55. private:
  56.     pthread_t _tid;           // 线程id
  57.     std::string _thread_name; // 线程名
  58.     bool _isrunning;          // 线程是否运行
  59.     func_t<T> _func;             // 线程所执行任务
  60.     T _data;                   // 传递数据类型
  61. };
复制代码

  

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

缠丝猫

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表