POSIX 线程
POSIX 线程也被简称为 Pthreads,是一个线程的 POSIX 标准。
1 #include <pthread.h> 2 3 int pthread_create( 4 pthread_t* thread, 5 pthread_attr_t const* attr, 6 void* (*start_routine)(void*), 7 void* arg 8 );
参数:
1、指向 thread_t 类型变量的指针,函数用该指针返回新线程的句柄。
2、指向 pthread_attr_t 结构的指针形式存在的新线程属性,可以通过该属性指定新线程的栈基址、栈大小、守护大小、调度策略和调度优先级等。
3、指向线程启动程序的函数指针,启动程序函数签名格式如下:
void* start_routine(void* args)
启动程序将线程参数看成 void 指针,返回 void 指针类型结果。
当线程以空指针的形式执行时,参数都需要被传递给启动程序,如果不需要传递参数,它可以为空指针。成功时,pthread_create 函数返回 0,否则返回一个错误代码。
示例代码
1 #include <stdio.h> 2 #include <unistd.h> 3 4 // POSIX 线程 5 #include <pthread.h> 6 7 #include "com_apress_threads_MainActivity.h" 8 9 // Native worker thread arguments 10 // 原生 worker 线程参数 11 struct NativeWorkerArgs 12 { 13 jint id; 14 jint iterations; 15 }; 16 17 // Method ID can be cached 方法 ID 能被缓存 18 static jmethodID gOnNativeMessage = NULL; 19 20 // Java VM interface pointer Java 虚拟机接口指针 21 static JavaVM* gVm = NULL; 22 23 // Global reference to object 对象的全局引用 24 static jobject gObj = NULL; 25 26 // Mutex instance 互斥实例 27 static pthread_mutex_t mutex; 28 29 // 在原生代码中获取 Java 虚拟机接口指针 30 // 当共享库开始加载时虚拟机自动调用 JNI_OnLoad 函数 31 jint JNI_OnLoad (JavaVM* vm, void* reserved) 32 { 33 // Cache the JavaVM interface pointer 缓存 Java 虚拟机接口指针 34 gVm = vm; 35 36 return JNI_VERSION_1_4; 37 } 38 39 void Java_com_apress_threads_MainActivity_nativeInit ( 40 JNIEnv* env, 41 jobject obj) 42 { 43 // Initialize mutex 初始化互斥 44 if (0 != pthread_mutex_init(&mutex, NULL)) 45 { 46 // Get the exception class 获取异常类 47 jclass exceptionClazz = env->FindClass("java/lang/RuntimeException"); 48 49 // Throw exception 抛出异常 50 env->ThrowNew(exceptionClazz, "Unable to initialize mutex"); 51 goto exit; 52 } 53 54 // If object global reference is not set 如果对象的全局引用未设置 55 if (NULL == gObj) 56 { 57 // Create a new global reference for the object 为对象创建一个新的全局引用 58 gObj = env->NewGlobalRef(obj); 59 60 if (NULL == gObj) 61 { 62 goto exit; 63 } 64 } 65 66 // If method ID is not cached 如果方法 ID 没被缓存 67 if (NULL == gOnNativeMessage) 68 { 69 // Get the class from the object 从对象中获取类 70 jclass clazz = env->GetObjectClass(obj); 71 72 // Get the method id for the callback 为回调获取方法 ID 73 gOnNativeMessage = env->GetMethodID(clazz, 74 "onNativeMessage", 75 "(Ljava/lang/String;)V"); 76 77 // If method could not be found 如果方法没有找到 78 if (NULL == gOnNativeMessage) 79 { 80 // Get the exception class 获取异常类 81 jclass exceptionClazz = env->FindClass("java/lang/RuntimeException"); 82 83 // Throw exception 抛出异常 84 env->ThrowNew(exceptionClazz, "Unable to find method"); 85 } 86 } 87 88 exit: 89 return; 90 } 91 92 void Java_com_apress_threads_MainActivity_nativeFree ( 93 JNIEnv* env, 94 jobject obj) 95 { 96 // If object global reference is set 如果对象的全局引用已设置 97 if (NULL != gObj) 98 { 99 // Delete the global reference 删除全局引用,以免内存泄漏 100 env->DeleteGlobalRef(gObj); 101 gObj = NULL; 102 } 103 104 // Destory mutex 销毁互斥锁 105 if (0 != pthread_mutex_destroy(&mutex)) 106 { 107 // Get the exception class 获取异常类 108 jclass exceptionClazz = env->FindClass("java/lang/RuntimeException"); 109 110 // Throw exception 抛出异常 111 env->ThrowNew(exceptionClazz, "Unable to destroy mutex"); 112 } 113 } 114 115 void Java_com_apress_threads_MainActivity_nativeWorker ( 116 JNIEnv* env, 117 jobject obj, 118 jint id, 119 jint iterations) 120 { 121 // Lock mutex 锁定互斥锁 122 if (0 != pthread_mutex_lock(&mutex)) 123 { 124 // Get the exception class 获取异常类 125 jclass exceptionClazz = env->FindClass("java/lang/RuntimeException"); 126 127 // Throw exception 抛出异常 128 env->ThrowNew(exceptionClazz, "Unable to lock mutex"); 129 goto exit; 130 } 131 132 // Loop for given number of iterations 循环给定的迭代数 133 for (jint i = 0; i < iterations; i++) 134 { 135 // Prepare message 准备消息 136 char message[26]; 137 sprintf(message, "Worker %d: Iteration %d", id, i); 138 139 // Message from the C string 来自 C 字符串的消息 140 jstring messageString = env->NewStringUTF(message); 141 142 // Call the on native message method 调用原生消息方法 143 env->CallVoidMethod(obj, gOnNativeMessage, messageString); 144 145 // Check if an exception occurred 检查是否产生异常 146 if (NULL != env->ExceptionOccurred()) 147 break; 148 149 // Sleep for a second 睡眠 1 秒 150 sleep(1); 151 } 152 153 // Unlock mutex 解锁互斥锁 154 if (0 != pthread_mutex_unlock(&mutex)) 155 { 156 // Get the exception class 获取异常类 157 jclass exceptionClazz = env->FindClass("java/lang/RuntimeException"); 158 159 // Throw exception 抛出异常 160 env->ThrowNew(exceptionClazz, "Unable to unlock mutex"); 161 } 162 163 exit: 164 return; 165 } 166 167 static void* nativeWorkerThread (void* args) 168 { 169 JNIEnv* env = NULL; 170 171 // Attach current thread to Java virtual machine 将当前线程附加到 Java 虚拟机上 172 // and obrain JNIEnv interface pointer 并且获得 JNIEnv 接口指针 173 if (0 == gVm->AttachCurrentThread(&env, NULL)) 174 { 175 // Get the native worker thread arguments 获取原生 worker 线程参数 176 NativeWorkerArgs* nativeWorkerArgs = (NativeWorkerArgs*) args; 177 178 // Run the native worker in thread context 在线程上下文中运行原生 worker 179 Java_com_apress_threads_MainActivity_nativeWorker(env, 180 gObj, 181 nativeWorkerArgs->id, 182 nativeWorkerArgs->iterations); 183 184 // Free the native worker thread arguments 释放原生 worker 线程参数 185 delete nativeWorkerArgs; 186 187 // Detach current thread from Java virtual machine 从 Java 虚拟机中分离当前线程 188 gVm->DetachCurrentThread(); 189 } 190 191 return (void*) 1; 192 } 193 194 void Java_com_apress_threads_MainActivity_posixThreads ( 195 JNIEnv* env, 196 jobject obj, 197 jint threads, 198 jint iterations) 199 { 200 // 线程句柄 201 pthread_t* handles = new pthread_t(threads); 202 203 // Create a POSIX thread for each worker 为每一个 worker 创建一个 POSIX 线程 204 for (jint i = 0; i < threads; i++) 205 { 206 // Thread handle 线程句柄 207 pthread_t thread; 208 209 // Native worker thread arguments 原生 worker 线程参数 210 NativeWorkerArgs* nativeWorkerArgs = new NativeWorkerArgs(); 211 nativeWorkerArgs->id = i; 212 nativeWorkerArgs->iterations = iterations; 213 214 // Create a new thread 创建一个新线程 215 int result = pthread_create( 216 //&thread, 217 &handles[i], 218 NULL, 219 nativeWorkerThread, 220 (void*) nativeWorkerArgs); 221 222 if (0 != result) 223 { 224 // Get the exception class 获取异常类 225 jclass exceptionClazz = env->FindClass("java/lang/RuntimeException"); 226 227 // Throw exception 抛出异常 228 env->ThrowNew(exceptionClazz, "Unable to create thread"); 229 goto exit; 230 } 231 } 232 233 // 等待线程中止 234 for(jint i = 0; i < threads; i++) 235 { 236 void* result = NULL; 237 238 // 连接每个线程句柄 239 if( 0 != pthread_join( handles[i], &result)) 240 { 241 // Get the exception class 获取异常类 242 jclass exceptionClazz = env->FindClass("java/lang/RuntimeException"); 243 244 // Throw exception 抛出异常 245 env->ThrowNew(exceptionClazz, "Unable to create thread"); 246 }else{ 247 // 准备 message 248 char message[26]; 249 sprintf(message, "Worker %d returned %d", i, result); 250 251 // 来自 C 字符串的消息 252 jstring messageString = env->NewStringUTF(message); 253 254 // 调用原生消息方法 255 env->CallVoidMethod(obj, gOnNativeMessage, messageString); 256 257 // 检查是否产生异常 258 if (NULL != env->ExceptionOccurred()) 259 { 260 goto exit; 261 } 262 } 263 } 264 exit: 265 return; 266 }
使用信号量同步 POSIX 线程
1 #include <semaphore.h> 2 3 // 初始化信号量 4 extern int sem_init(sem_t* sem, int pshared, unsigned int value); 5 6 // 锁定信号量 7 extern int sem_wait(sem_t* sem); 8 9 // 解锁信号量 10 extern int sem_post(sem_t* sem); 11 12 // 销毁信号量 13 extern int sem_destroy(sem_t* sem);
POSIX 线程调度策略
int pthread_setschedparam(pthread_t thid, int poilcy, struct sched_param const* param);
POSIX Thread 优先级

浙公网安备 33010602011771号