先创建两个需要在子线程中执行的函数
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 销毁信号量
网友评论