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 优先级

posted @ 2015-07-06 22:05  壬子木  阅读(200)  评论(0)    收藏  举报