NDK03

作者: 星云春风 | 来源:发表于2020-05-21 23:49 被阅读0次

    结构体

    结构体里所有的成员,都是public的

    // TODO xia chen hui 2020/5/21 21:58 结构体
    struct Student {
        // xia chen hui 2020/5/21 21:59 里面所有的成员,都是public
        char *name;
        int age;
        char sex;
    };
    
    

    共用体

    在内存中只存在一个值

    // TODO xia chen hui 2020/5/21 22:18 共用体
    union MyCount {
        int countValue1;
        int countValue2;
        int countValue3;
        int countValue4;
        int countValue5;
        int countValue6;
        int countValue7;
    };
        // TODO xia chen hui 2020/5/21 22:20 共用体
        union MyCount myCount;
        myCount.countValue1 = 10;
        printf("myCount的值%d\n", myCount.countValue1); //输出10
        myCount.countValue2 = 20;
        printf("myCount的值%d\n", myCount.countValue1);//输出20,countValue1的值被改了
    
    

    分离线程和非分离线程

    分离线程:线程之间自己管自己,不管其他的,所以不管线程是否执行完毕,该结束就结束。
    非分离线程:先执行异步任务,要等到耗时任务完成之后,才会执行join后面的关联代码

    • 线程是有步骤
    CmakeLists中
    # 第一步,引入线程库的所有头文件
    include_directories("C:/Users/Administrator/Desktop/pthreads-w32-2-9-1-release/Pre-built.2/include")
    # 第二步,引入线程库的库文件,链接到库
    link_directories("C:/Users/Administrator/Desktop/pthreads-w32-2-9-1-release/Pre-built.2/lib/x64")
    # 第三步,链接到目标库
    target_link_libraries(ndk03_code_cpp pthreadVC2)
    #第五步,解决宏没有定义的问题,但是第二步选择64位的时候,好像不需要这一步
    # cxx代表C++,
    # "${CMAKE_CXX_FLAGS}"  CMAKE_CXX_FLAGS =AAA/BB/CC....  表示不破坏他的配置,在他的配置基础上增加
    # -DHAVE_STRUCT_TIMESPEC代表增加HAVE_STRUCT_TIMESPEC这个宏,和D之间不能有空格
    #set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DHAVE_STRUCT_TIMESPEC")
    
    
    #第四步在cpp文件中是导入头文件
    #第六步,需要把C:\Users\Administrator\Desktop\pthreads-w32-2-9-1-release\Pre-built.2\dll 里的动态链接库pthreadVC2.dll交叉复制到C:\Windows的system32 和SysWOW64中。32复制到64  ,64复制到32
    
    • 线程普通用法
    //定义函数指针规则
    void *customPthreadMethod(void *pVoid) {
        //void *代表能接受所有类型
        // static_cast<int *>(pVoid)代表把空指针转换为int类型的指针,然后加上*取出内存地址对应的值
        int result = *static_cast<int *>(pVoid);
        printf("耗时任务被执行...%d\n", result);
        for (int i = 0; i < 50; ++i) {
            Sleep(200);
            printf("customPthreadMethod: i=%d\n", (i + 1));
        }
        //如果不返回,就会出现问题
        return 0;
    }
    
    //最简单有用法
    void simpleThreadTest() {
        cout << "124" << endl;
        pthread_t pthreadID;//线程ID
    // xia chen hui 2020/5/28 0:11 参数1.线程id  2.线程属性 3.函数指针,执行异步任务,类似java的run 4.函数指针的参数传递
        int value01 = 4512;
        //会把value01传给customPthreadMethod
        pthread_create(&pthreadID, 0, customPthreadMethod, &value01);
        //pthread_join会等待耗时任务执行完成之后,才会执行后面的代码
        pthread_join(pthreadID, 0);
        printf("线程执行完毕...");
    
    }
    
    • 线程升级用
    
    //线程升级用法
    void *customPthreadMethod2(void *pVoid) {
    
        float result = *static_cast<float *>(pVoid);
        printf("2耗时任务被执行...%f\n", result);
        for (int i = 0; i < 50; ++i) {
            Sleep(100);
            printf("customPthreadMethod2: i=%d\n", (i + 1));
        }
        return 0;
    }
    
    void customThreadTest() {
        pthread_t pthreadID;//允许有野指针
        pthread_attr_t pthreadAttr; //线程属性,不允许有野指针
        //需要初始化线程属性,需要指针类型,所以传内存地址
        pthread_attr_init(&pthreadAttr);
    
        // TODO xia chen hui 2020/5/28 23:38 分离线程 和 非分离线程
        // xia chen hui 2020/5/28 23:38  非分离线程:先执行异步任务,要等到耗时任务完成之后,才会执行join后面的关联代码
        // xia chen hui 2020/5/28 23:38 分离线程:线程之间自己管自己,不管其他的,所以不管线程是否执行完毕,该结束就结束。
    
        //开启分离线程。pthread_join会失效
        //pthread_attr_setdetachstate(&pthreadAttr, PTHREAD_CREATE_DETACHED);
    
    
        //开启非分离线程和pthread_join相关联
        pthread_attr_setdetachstate(&pthreadAttr, PTHREAD_CREATE_JOINABLE);
    
        float value = 12.3;
        pthread_create(&pthreadID, &pthreadAttr, customPthreadMethod2, &value);
        //耗时任务完成之后再执行 ,join第二个参数是线程执行完成后的返回结果
        pthread_join(pthreadID, 0);
        printf("customThreadTest线程完成之后...\n");
    
        //完成之后回收
        pthread_attr_destroy(&pthreadAttr);
    
    
    }
    
    • 线程互斥锁
    // TODO xia chen hui 2020/5/28 23:51 线程的升级,  线程安全问题 互斥锁
    #include <iostream>
    #include <pthread.h>
    #include <string>
    #include <queue>
    
    using namespace std;
    
    //定义全局的队列
    queue<int> saveAllData;
    
    //定义一个互斥锁,不允许野指针
    pthread_mutex_t mutex;
    
    void *customThreadMethod(void *pVoid) {
        // 10个线程,同时对队列的数据进行操作,并保证数据安全,(加锁)
        //加锁
        pthread_mutex_lock(&mutex);
        printf("当前线程标记是-----------%d\n", *static_cast<int *>(pVoid));
        if (!saveAllData.empty()) {
            printf("获取队列的数据:%d\n", saveAllData.front());
            //把数据弹出去(删除)
            saveAllData.pop();
        } else {
            printf("队列中没有数据了...");
        }
        //解锁,为了让其他线程可以进来操作
        pthread_mutex_unlock(&mutex);
        return 0;
    }
    
    int main() {
    
        //初始化互斥锁
        pthread_mutex_init(&mutex, NULL);
        //给队列初始化数据
        for (int j = 1000; j < 1030; ++j) {
            saveAllData.push(j);
        }
        //初始化线程id
        pthread_t pthreadIDArray[30];
        for (int i = 0; i < 30; ++i) {
            //for循环开启线程
            pthread_create(&pthreadIDArray[i], 0, customThreadMethod, &i);
        }
        //回收互斥锁
        pthread_mutex_destroy(&mutex);
        printf("main函数已经结束...");
    
        //阻塞main ,为了让多线程执行完成
        system("pause");
    
    
        return 0;
    }
    
    
    • 生产者 消费者
    // TODO xia chen hui 2020/5/29 20:29 生产者 消费者 工具类
    
    #ifndef NDK03_CODE_CPP_SAFE_QUEUE_TOOL_H
    #define NDK03_CODE_CPP_SAFE_QUEUE_TOOL_H
    
    #endif //NDK03_CODE_CPP_SAFE_QUEUE_TOOL_H
    
    #include <iostream>
    #include <string>
    #include <pthread.h>
    #include <queue>
    
    using namespace std;
    
    //定义一个模板
    template<typename T>
    
    class SafeQueueClass {
    private:
        //定义一个队列
        queue<T> queue;
        //定义互斥锁,为了线程安全处理 ,不允许有野指针
        pthread_mutex_t mutex;
        //定义条件变量,为了实现等待读取功能 ,不允许有野指针
        pthread_cond_t cond;
    public:
        //构造函数
        SafeQueueClass() {
            //初始化互斥锁
            pthread_mutex_init(&mutex, NULL);
            //初始化条件变量
            pthread_cond_init(&cond, NULL);
        }
    
        ~SafeQueueClass() {
            //回收互斥锁
            pthread_mutex_destroy(&mutex);
            //回收条件变量
            pthread_cond_destroy(&cond);
        }
    
        // TODO xia chen hui 2020/5/29 20:49 加入队列中(进行生产)
        void add(T t) {
            //为了保证同步的安全性,所以锁定
            pthread_mutex_lock(&mutex);
    
            queue.push(t);
            //这里需要唤醒消费者,否则消费者会一直等待,
            //pthread_cond_signal(&cond); //系统去唤醒一个线程,--java notify
            //唤醒所有的线程,---java notifyAll
            pthread_cond_broadcast(&cond);
            //解锁
            pthread_mutex_unlock(&mutex);
    
        }
    
        // TODO xia chen hui 2020/5/29 20:51 从队列中获取(进行消费)
        void get(T &t) {
            //为了保证同步的安全性,所以锁定
            pthread_mutex_lock(&mutex);
            //if 可能有问题,
            while (queue.empty()) {
                //没有数据可以消费了,所以开始等待
                pthread_cond_wait(&cond, &mutex);//用if 等待之后,可能会被系统唤醒
            }
    
    
            //证明已经被唤醒了,开始消费
            //取出首元素,得到队里中的数据
            t = queue.front();
            //把数据弹出去(删除)
            queue.pop();
    
            //解锁
            pthread_mutex_unlock(&mutex);
        }
    };
    
    #include "safe_queue_tool.h"
    
    
    using namespace std;
    
    SafeQueueClass<int> safeQueueClass;
    
    // TODO xia chen hui 2020/5/29 21:04 模拟消费者
    void *getMethod(void *pVoid) {
        //非0 就是true
        while (1) {
            int value;
            safeQueueClass.get(value); //这里value 就有值了
            printf("getMethod的value =%d\n", value);
            //为了结束循环,如果输入-1, 就结束
            if (-1 == value) {
                printf("消费者执行完毕...\n");
                break;
            }
        }
        return 0;
    }
    
    // TODO xia chen hui 2020/5/29 21:05 模拟生产者
    void *setMethod(void *pVoid) {
        while (1) {
            printf("setMethod\n");
            printf("请输入信息....\n");
            int value;
            cin >> value;
            //为了结束循环,如果输入-1, 就结束
            if (-1 == value) {
                //为了让消费者可以获取-1  进行停止
                safeQueueClass.add(value);
                printf("生产者执行完毕...\n");
                break;
            }
            //添加进去
            safeQueueClass.add(value);
    
        }
        return 0;
    }
    
    int main() {
        pthread_t pthreadGet;
        pthread_t pthreadSet;
    
        pthread_create(&pthreadGet, 0, getMethod, 0);
        pthread_create(&pthreadSet, 0, setMethod, 0);
    
        pthread_join(pthreadGet, 0);
        pthread_join(pthreadSet, 0);
        printf("main函数执行...\n");
    
        return 0;
    }
    

    相关文章

      网友评论

          本文标题:NDK03

          本文链接:https://www.haomeiwen.com/subject/bvdxahtx.html