如何从JNI启动新线程

时间:2014-05-26 14:43:28

标签: android c++ multithreading java-native-interface

我需要从android应用程序的本机部分启动一个新线程。它必须在JNI中声明和定义。有人知道我该怎么办?如果有人发布这个例子,我会非常高兴。

1 个答案:

答案 0 :(得分:10)

最简单的方法是使用C ++ 11线程类。有关如何使用Android NDK启用C ++ 11,请参阅this topic。如果您在使线程类工作时遇到问题,请参阅this post。然后你可以像这样使用它:

#include <thread>         // std::thread

void foo() 
{
   // do stuff...
}

void bar(int x)
{
   // do stuff...
}

JNIEXPORT void JNICALL 
Java_org_testjni_android_Game_someFunction(JNIEnv * env, jobject  obj)
{
   std::thread first (foo);     // spawn new thread that calls foo()
   std::thread second (bar,0);  // spawn new thread that calls bar(0)

    //main, foo and bar now execute concurrently

    // synchronize threads:
   first.join();                // pauses until first finishes
   second.join();               // pauses until second finishes

}

如果你不能使用C ++ 11,那就使用pthread(POSIX线程),它没有什么不同,除了它像旧的C:

#include <pthread.h>

    //This function will be called from a thread

void *call_from_thread(void *) {
    //do stuff
    return NULL;
}

JNIEXPORT void JNICALL 
Java_org_testjni_android_Game_someFunction(JNIEnv * env, jobject  obj)
{
        pthread_t t;

        //Launch a thread
        pthread_create(&t, NULL, call_from_thread, NULL);

        //Join the thread with the main thread
        pthread_join(t, NULL);
 }

这里有一些关于在Android上使用POSIX线程的more info

如果你想在任何线程中使用它而不是调用JNI函数的线程,你还需要查找如何将JNIEnv指针绑定到当前线程。来自JNI规范:

  

创建VM

     

JNI_CreateJavaVM()函数加载并初始化Java VM和   返回指向JNI接口指针的指针。调用的线程   JNI_CreateJavaVM()被认为是主线程。

     

附加到VM

     

JNI接口指针(JNIEnv)仅在当前有效   线。如果另一个线程需要访问Java VM,它必须   首先调用AttachCurrentThread()将自身附加到VM并获取   一个JNI接口指针。一旦附加到VM,就是本机线程   就像在本机中运行的普通Java线程一样工作   方法。本机线程保持连接到VM,直到它调用   DetachCurrentThread()分离自己。

     

附加的线程应该有足够的堆栈空间来执行   合理的工作量。每个线程的堆栈空间分配是   特定于操作系统。例如,使用pthreads,堆栈大小   可以在pthread_create的pthread_attr_t参数中指定。

     

从VM中分离

     

连接到VM的本机线程必须调用DetachCurrentThread()   退出前脱离自己。如果有线程,则线程无法分离   是调用堆栈上的Java方法。