对于原生代码使用Java线程的优缺点
?? 對于原生的代碼使用Java線程與原生的線程相比有一下的優點:
?? 它是很容易建立的。
?? 在原生代碼不需要任何改變
? 它不需要明確的附加到這虛擬機,Java線程已經是Java平臺的一部分。原生代碼和Java代碼通信使用線程指定的JNIEnv接口指針。
? 方法被提供通過java.lang.Thread類能夠被用無縫的和線程實例溝通。
? 除了它的優勢,這Java線程有這主要短缺與原生線程相比當對于多線程的原生代碼:
???? 假定這邏輯分配任務到線程是Java代碼的部分,因為在原生區域來創建Java線程沒有API。
??? 假定這原生代碼是線程安全的,因為基于Java的線程是透明對于這原生代碼。
?? 原生代碼不能從其他同伴編程內容和組件獲益,例如信號量,因為沒有API對于原生代碼。
?? 原生代碼運行在一個單獨的新車不能交流或者直接分享資源。
POSIX 線程
POSIX線程,也是作為簡單Pthreads,是一個POSIX標準對于線程。
在原生代碼中使用POSIX線程
??? 這POSIX線程API通過pthread.h頭文件被定義。為了使用POSIX線程在原生代碼,這頭文件需要首先被包含。
?? #include<pthread.h>
?? 這Android實現POSIX線程是BIONIC標準C庫 的一部分。不像其他的平臺,在編譯時不需要連接其他的額外庫。
? 使用pthread_create創建線程
? int pthread_create(pthread_t* thread,pthread_attr_t const* attr,void* (*start_routine)(void*),
void* arg);
??????????????????? 這個函數的參數是:
???? 一個thread_t類型的指針變量被函數利用來返回對于這新線程的的句柄。
??? 以pthread_attr_t結構體的指針是新線程的屬性。棧的基地址,棧的大小,防衛大小,調度策略和對于新線程的調度游戲級通過這個屬性來指定。你將學到一些屬性。使用默認屬性時,使用NULL。
?? 一個函數指針對于開始路徑對于這個線程。這個開始路徑函數的簽名應該看下面:
???? void* start_rountine(void* args);
? 這開始路徑去線程參數作為一個空指針,和它返回作為一個空指針作為結果。
任何參數應該被傳遞給開始路徑當線程以一個void指針個等到執行。如果沒有承諾書需要傳遞,返回NULL。
?? pthread_create函數將返回0;否則他將返回一個錯誤代碼。
有多重的方法來獲得Java VM接口指針。這容易和恰當的方式做這通過這JNI_OnLoad函數。這個函數得到自動觸發由虛擬機當一個共享庫被加載。這個函數去Java Vm接口指針作為它的一個參數。如下,增加這JNI_OnLoad函數到本地為了存儲Java Vm接口指針在gVm全局變量被地你故意在上一步。
#include <pthread.h>
// Native worker thread arguments
struct NativeWorkerArgs
{
jint id;
jint iterations;
};
// Method ID can be cached
static jmethodID gOnNativeMessage = NULL;
// Java VM interface pointer
static JavaVM* gVm = NULL;
// Global reference to object
static jobject gObj = NULL;
void Java_com_apress_threads_MainActivity_nativeInit (
JNIEnv* env,
jobject obj)
?
?
????? jint JNI_OnLoad(JavaVM* vm,void* reserved)
???? {
???????? //Cache 這JavaVM接口指針
??????? gVm=vm;
??????? return JNI_VERSION_1_4;
???????????????
???? }
?
?
void Java_com_apress_threads_MainActivity_nativeInit (
JNIEnv* env,
jobject obj)
{
// If object global reference is not set
if (NULL == gObj)
{
// Create a new global reference for the object
gObj = env->NewGlobalRef(obj);
if (NULL == gObj)
{
goto exit;
}
}
// If method ID is not cached
if (NULL == gOnNativeMessage)
...
exit:
return;
}
?
void Java_com_apress_threads_MainActivity_nativeFree (
JNIEnv* env,
jobject obj)
{
// If object global reference is set
if (NULL != gObj)
{
// Delete the global reference
env->DeleteGlobalRef(gObj);
gObj = NULL;
}
}
...
?
?
static void* nativeWorkerThread (void* args)
{
JNIEnv* env = NULL;
// Attach current thread to Java virtual machine
// and obrain JNIEnv interface pointer
if (0 == gVm->AttachCurrentThread(&env, NULL))
{
// Get the native worker thread arguments
NativeWorkerArgs* nativeWorkerArgs = (NativeWorkerArgs*) args;
// Run the native worker in thread context
Java_com_apress_threads_MainActivity_nativeWorker(env,
gObj,
nativeWorkerArgs->id,
nativeWorkerArgs->iterations);
// Free the native worker thread arguments
delete nativeWorkerArgs;
// Detach current thread from Java virtual machine
gVm->DetachCurrentThread();
}
return (void*) 1;
}
??? 從線程中返回結果:
當他們終止時,線程能夠返回一個結果。通過這空指針這能夠被獲得從這線程開始路徑。在上一個例子中,這Java_com_apress_threads_MainActivity_PosixThreads函數被設計來直接返回在執行這線程后。這個函數被修改來等待線程來完成他們的工作和返回。一個函數能夠等待一個線程通過使用pthread_join函數來終止。
?? int pthread_join(pthread_t thread,void** ret_val);
這Pthread_join函數的參數:
?????? 線程句柄有pthread_create函數對于目標線程的返回。
????? 獲得這個返回結果從開始路徑的指針。
它阻止這調用線程的執行直到這目標線程終止。如果這ret_val不是NULL,這個函數將設置ret_val指針值返回這開始的路徑。pthread_join返回0;否則返回錯誤代碼。
?
?
?
總結
以上是生活随笔為你收集整理的对于原生代码使用Java线程的优缺点的全部內容,希望文章能夠幫你解決所遇到的問題。