美文网首页
NDK基础(五)—— 线程

NDK基础(五)—— 线程

作者: 王志强_9380 | 来源:发表于2020-06-29 15:14 被阅读0次

    先创建两个需要在子线程中执行的函数

    
    void* NativeThread1(int args) {
        JNIEnv *env = NULL;
        if(mVm->AttachCurrentThread(&env, NULL) == 0) {
    
            for (int i = 0; i < args; ++i) {
                LOGE("NativeThread1 %d", i);
                sleep(1);
            }
    
            mVm->DetachCurrentThread();
        }
        return reinterpret_cast<void *>(1);
    }
    
    int NativeThread2() {
        JNIEnv *env = NULL;
        if(mVm->AttachCurrentThread(&env, NULL) == 0) {
            for (int i = 0; i < 10; ++i) {
                LOGE("NativeThread2 %d", i);
                sleep(1);
            }
            mVm->DetachCurrentThread();
        }
        return 100;
    }
    

    由于JNI中的线程不是Java平台的一部分,因此虚拟机不能识别他们,为了和Java空间交互,线程应该先将自己附着到虚拟机上,所以在执行线程中的方法时,需要调用AttachCurrentThread和DetachCurrentThread

    创建一个新的线程

    int pthread_create(pthread_t* __pthread_ptr, pthread_attr_t const* __attr, void* (__start_routine)(void), void* arg);
    __pthread_ptr:新线程的句柄
    __attr:指定新线程的栈基址、栈大小、守护大小、调度策略和调度优先级等
    __start_routine:启动程序的函数指针
    arg:传递给start_routine的参数

    pthread_t pthread1;
    pthread_t pthread2;
    int thread1count = 7;
    pthread_create(&pthread1, NULL, reinterpret_cast<void *(*)(void *)>(NativeThread1),
                   reinterpret_cast<void *>(thread1count));
    pthread_create(&pthread2, NULL, reinterpret_cast<void *(*)(void *)>(NativeThread2), NULL);
    

    释放一个线程的内存空间

    如果一个线程是非分离的(默认情况下创建的线程都是非分离)并且没有对该线程使用方法释放内存的话,该线程结束后并不会释放其内存空间,这会导致该线程变成了“僵尸线程”

    int pthread_join(pthread_t __pthread, void** __return_value_ptr);
    __pthread:线程的句柄
    __return_value_ptr:返回值
    当前线程会处于阻塞状态,直到被调用的线程结束后,当前线程才会重新开始执行

    extern "C"
    JNIEXPORT void JNICALL
    Java_com_example_ffmpegapplication_NativeStudy_ThreadTest(JNIEnv *env, jobject instance) {
    
        LOGE("ThreadTest start");
        pthread_t pthread1;
        pthread_t pthread2;
        int thread1count = 7;
        pthread_create(&pthread1, NULL, reinterpret_cast<void *(*)(void *)>(NativeThread1),
                       reinterpret_cast<void *>(thread1count));
        pthread_create(&pthread2, NULL, reinterpret_cast<void *(*)(void *)>(NativeThread2), NULL);
    
        if(0 == pthread_join(pthread1, NULL)){
            LOGE("NativeThread1 end");
        }
        void* result;
        if(0 == pthread_join(pthread2, &result)){
            LOGE("NativeThread2 end %d", result);
        }
        LOGE("ThreadTest end");
    }
    
    结果:
    11-18 16:01:16.276: E/wzq(31275): ThreadTest start
    11-18 16:01:16.278: E/wzq(31275): NativeThread1 0
    11-18 16:01:16.281: E/wzq(31275): NativeThread2 0
    11-18 16:01:17.279: E/wzq(31275): NativeThread1 1
    11-18 16:01:17.282: E/wzq(31275): NativeThread2 1
    11-18 16:01:18.280: E/wzq(31275): NativeThread1 2
    11-18 16:01:18.283: E/wzq(31275): NativeThread2 2
    11-18 16:01:19.280: E/wzq(31275): NativeThread1 3
    11-18 16:01:19.283: E/wzq(31275): NativeThread2 3
    11-18 16:01:20.280: E/wzq(31275): NativeThread1 4
    11-18 16:01:20.284: E/wzq(31275): NativeThread2 4
    11-18 16:01:21.281: E/wzq(31275): NativeThread1 5
    11-18 16:01:21.284: E/wzq(31275): NativeThread2 5
    11-18 16:01:22.282: E/wzq(31275): NativeThread1 6
    11-18 16:01:22.285: E/wzq(31275): NativeThread2 6
    11-18 16:01:23.283: E/wzq(31275): NativeThread1 end
    11-18 16:01:23.285: E/wzq(31275): NativeThread2 7
    11-18 16:01:24.286: E/wzq(31275): NativeThread2 8
    11-18 16:01:25.286: E/wzq(31275): NativeThread2 9
    11-18 16:01:26.287: E/wzq(31275): NativeThread2 end 100
    11-18 16:01:26.287: E/wzq(31275): ThreadTest end
    
    

    int pthread_detach(pthread_t __pthread);
    __pthread:线程的句柄
    当前线程不会阻塞

    extern "C"
    JNIEXPORT void JNICALL
    Java_com_example_ffmpegapplication_NativeStudy_ThreadTest(JNIEnv *env, jobject instance) {
    
        LOGE("ThreadTest start");
        pthread_t pthread1;
        pthread_t pthread2;
        int thread1count = 7;
        pthread_create(&pthread1, NULL, reinterpret_cast<void *(*)(void *)>(NativeThread1),
                       reinterpret_cast<void *>(thread1count));
        pthread_create(&pthread2, NULL, reinterpret_cast<void *(*)(void *)>(NativeThread2), NULL);
    
        if(0 == pthread_detach(pthread1)) {
            LOGE("NativeThread1 end");
        }
        if(0 == pthread_detach(pthread2)) {
            LOGE("NativeThread2 end");
        }
    
        LOGE("ThreadTest end");
    }
    
    结果:
    11-18 16:03:41.813: E/wzq(31590): ThreadTest start
    11-18 16:03:41.813: E/wzq(31590): NativeThread1 end
    11-18 16:03:41.813: E/wzq(31590): NativeThread2 end
    11-18 16:03:41.813: E/wzq(31590): ThreadTest end
    11-18 16:03:42.814: E/wzq(31590): NativeThread1 0
    11-18 16:03:42.819: E/wzq(31590): NativeThread2 0
    11-18 16:03:42.814: E/wzq(31590): NativeThread1 1
    11-18 16:03:42.819: E/wzq(31590): NativeThread2 1
    11-18 16:03:43.815: E/wzq(31590): NativeThread1 2
    11-18 16:03:43.819: E/wzq(31590): NativeThread2 2
    11-18 16:03:44.815: E/wzq(31590): NativeThread1 3
    11-18 16:03:44.820: E/wzq(31590): NativeThread2 3
    11-18 16:03:45.816: E/wzq(31590): NativeThread1 4
    11-18 16:03:45.820: E/wzq(31590): NativeThread2 4
    11-18 16:03:46.816: E/wzq(31590): NativeThread1 5
    11-18 16:03:46.821: E/wzq(31590): NativeThread2 5
    11-18 16:03:47.817: E/wzq(31590): NativeThread1 6
    11-18 16:03:47.821: E/wzq(31590): NativeThread2 6
    11-18 16:03:48.822: E/wzq(31590): NativeThread2 7
    11-18 16:03:49.822: E/wzq(31590): NativeThread2 8
    11-18 16:03:50.823: E/wzq(31590): NativeThread2 9
    
    

    互斥锁

    pthread_mutex_init 初始化互斥锁
    pthread_mutex_destroy 释放互斥锁
    pthread_mutex_lock 锁定互斥锁
    pthread_mutex_unlock 解锁互斥锁

    修改一下方法,加上互斥锁

    void* NativeThread1(int args) {
    
        pthread_mutex_lock(&mutex);
        JNIEnv *env = NULL;
        if(mVm->AttachCurrentThread(&env, NULL) == 0) {
    
            for (int i = 0; i < args; ++i) {
                LOGE("NativeThread1 %d", i);
                sleep(1);
            }
    
            mVm->DetachCurrentThread();
        }
        pthread_mutex_unlock(&mutex);
        return reinterpret_cast<void *>(1);
    }
    
    int NativeThread2() {
    
        pthread_mutex_lock(&mutex);
        JNIEnv *env = NULL;
        if(mVm->AttachCurrentThread(&env, NULL) == 0) {
            for (int i = 0; i < 10; ++i) {
                LOGE("NativeThread2 %d", i);
                sleep(1);
            }
            mVm->DetachCurrentThread();
        }
        pthread_mutex_unlock(&mutex);
        return 100;
    }
    
    结果:
    11-18 16:23:22.695: E/wzq(1781): NativeThread2 1
    11-18 16:23:23.695: E/wzq(1781): NativeThread2 2
    11-18 16:23:24.696: E/wzq(1781): NativeThread2 3
    11-18 16:23:25.697: E/wzq(1781): NativeThread2 4
    11-18 16:23:26.697: E/wzq(1781): NativeThread2 5
    11-18 16:23:27.698: E/wzq(1781): NativeThread2 6
    11-18 16:23:28.698: E/wzq(1781): NativeThread2 7
    11-18 16:23:29.699: E/wzq(1781): NativeThread2 8
    11-18 16:23:30.699: E/wzq(1781): NativeThread2 9
    11-18 16:23:31.702: E/wzq(1781): NativeThread1 0
    11-18 16:23:32.702: E/wzq(1781): NativeThread1 1
    11-18 16:23:33.703: E/wzq(1781): NativeThread1 2
    11-18 16:23:34.703: E/wzq(1781): NativeThread1 3
    11-18 16:23:35.704: E/wzq(1781): NativeThread1 4
    11-18 16:23:36.705: E/wzq(1781): NativeThread1 5
    11-18 16:23:37.705: E/wzq(1781): NativeThread1 6
    

    信号量

    sem_init 初始化信号量
    sem_wait 锁定信号量,成功的话,信号量减1,否则线程挂起等待信号量
    sem_post 解锁信号量,成功的话,信号量加1
    sem_destory 销毁信号量

    相关文章

      网友评论

          本文标题:NDK基础(五)—— 线程

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