【Linux】多线程_2


九、多线程

2. 线程的控制

主线程退出 等同于 进程退出 等同于 所有线程都退出。为了避免主线程退出,但是新线程并没有执行完自己的任务的问题,主线程同样要跟进程一样等待新线程返回。
在这里插入图片描述
pthread_join 函数则可以等待新线程返回。
Makefile

test_thread: testThread.cc
	g++ -o $@ $^ -std=c++11 -lpthread
.PHONY: clean
clean:
	rm -f test_thread

testThread.cc

#include <iostream>
#include <pthread.h>
#include <unistd.h>
using namespace std;

// 新线程
void* newpthreadrun(void* arg)
{
    int cnt = 5;
    while (cnt--)
    {
        cout << "I am newpthreadrun thread" << endl;
        sleep(1);
    }
}

int main()
{
    pthread_t tid;
    pthread_create(&tid, nullptr, newpthreadrun, nullptr);

    // 主线程
    pthread_join(tid, nullptr);

    cout << "I am main thread" << endl;
    sleep(5);

    return 0;
}

在这里插入图片描述
多线程中,任何一个线程出现异常,都会导致整个进程退出 ---- 多线程代码往往健壮性不好。 不能用 exit() 来退出线程,因为 exit() 是退出进程的,可以使用 pthread_exit() 来退出线程,也可以在主线程中使用 pthread_cancel() 来取消新线程线程,新线程会返回 -1。
我们来创建一个多线程:
Makefile

test_thread: testThread.cc
	g++ -o $@ $^ -std=c++11 -lpthread
.PHONY: clean
clean:
	rm -f test_thread

testThread.cc

#include <iostream>
#include <string>
#include <pthread.h>
#include <unistd.h>
#include <vector>
#include <cstdio>
#include <cstdlib>
using namespace std;

const int threadnum = 5;

// 加法任务
class Task
{
public:
    Task(int x, int y)
    :datax(x)
    ,datay(y)
    {}

    int Excute()
    {
        return datax + datay;
    }

    ~Task() {}
private:
    int datax;
    int datay;
};

// 线程数据
class ThreadData
{
public:
    ThreadData(int x, int y, const string& threadname)
    :t(x, y)
    ,threadname(threadname)
    {}

    string Threadname()
    {
        return threadname;
    }

    int run()
    {
        return t.Excute();
    }

    ~ThreadData() {}
private:
    string threadname;
    Task t;
};

// 执行任务后的结果
class Result
{
public:
    Result() {}

    void SetResult(int result, const string& threadname)
    {
        _result = result;
        _threadname = threadname;
    }

    void Print()
    {
        cout << _threadname << " run result: " << _result << endl;
    }

    ~Result() {}
private:
    int _result;
    string _threadname;
};

// 线程执行任务
void* handlerTask(void* args)
{
    ThreadData* td = static_cast<ThreadData*>(args);
    string name = td->Threadname();
    Result* res = new Result();
    int result = td->run();
    res->SetResult(result, name);

    return res;
}

int main()
{
    // 创建线程并分配任务
    vector<pthread_t> threads;
    for (int i = 0; i < threadnum; i++)
    {
        char threadname[64];
        snprintf(threadname, 64, "Thread-%d", i + 1);
        ThreadData* td = new ThreadData(10, 20, threadname);
        pthread_t tid;
        pthread_create(&tid, nullptr, handlerTask, td);
        threads.push_back(tid);
    }

    // 等待线程执行完毕并获取结果
    vector<Result*> result_set;
    void* ret = nullptr;
    for (auto& tid : threads)
    {
        pthread_join(tid, &ret);
        result_set.push_back((Result*)(ret));
    }

    // 打印结果
    for (auto& res : result_set)
    {
        res->Print();
        delete res;
    }

    return 0;
}

执行结果:
在这里插入图片描述


未完待续

相关推荐

  1. Linux线

    2024-07-09 23:52:07       70 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-07-09 23:52:07       67 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-07-09 23:52:07       71 阅读
  3. 在Django里面运行非项目文件

    2024-07-09 23:52:07       58 阅读
  4. Python语言-面向对象

    2024-07-09 23:52:07       69 阅读

热门阅读

  1. PAM(Pluggable Authentication Modules)如何配置

    2024-07-09 23:52:07       22 阅读
  2. py每日spider案例之音乐搜索

    2024-07-09 23:52:07       17 阅读
  3. 分享四款常见的内网穿透工具

    2024-07-09 23:52:07       27 阅读
  4. 深入理解 KVO

    2024-07-09 23:52:07       24 阅读
  5. 设计模式对比

    2024-07-09 23:52:07       20 阅读
  6. 浅谈贝叶斯定理

    2024-07-09 23:52:07       21 阅读
  7. ClickHouse中PRIMARY KEY和ORDER BY关键字的关系

    2024-07-09 23:52:07       20 阅读
  8. 基于Go 1.19的站点模板爬虫

    2024-07-09 23:52:07       24 阅读
  9. C++中的进程和线程的通信交互

    2024-07-09 23:52:07       23 阅读