美文网首页
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