王学岗NDK系列(六)JNI多线程+JNI_OnLoad

一:JNI多线程
1,android中的进程和线程
java虚拟机叫jvm,一个java程序可能有多个jvm,android虚拟机Dalvik vm,现在转化为ART VM(android run time),一个android的APP就是一个虚拟机,与java不同,java可以是多进程的,但是android APP只有一个进程(android 系统可以有多个进程),
2.POSIX标准UNIX族类系统(可移植操作系统接口)线程库pthread
3.android libc,bionic为pthreads提供了内置的支持,所以没有必要额外的链接(-lpthreads)。它并没有实现完整的POSIX线程功能,并且不支持读/写锁,pthread_cancel(),互斥进程共享和条件变量以及其他更高级的功能。
TLS,线程本地存储,限制为59 个可用于应用程序的pthread_key_t插槽,低于posix最低的128个
看下MainActivity类

package com.example.acer.test_18_02_26;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {

    // Used to load the 'native-lib' library on application startup.
    static {
        System.loadLibrary("native-lib");
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        System.out.println("张欣念我一生一世"+Thread.currentThread().getName().toString());
        // Example of a call to a native method
        TextView tv = (TextView) findViewById(R.id.sample_text);
        tv.setText(stringFromJNI());
    }

    /**
     * A native method that is implemented by the 'native-lib' native library,
     * which is packaged with this application.
     */
    public native String stringFromJNI();
    public void temp(){
        System.out.println("张欣念我一生一世"+Thread.currentThread().getName().toString());
    }
}

native-lib文件

#include <jni.h>
#include <string>

//#include <pthread.h>在android中不需要引入
//获取存放虚拟机的对象,把当前的进程拿下来
JavaVM *j_vm;
//定义一个新线程的对象,
pthread_t new_thread;

//声明一个线程调用的方法
void *run(void *);

//回调java的方法的id
jmethodID callBack;
extern "C"
JNIEXPORT jstring

JNICALL
Java_com_example_acer_test_118_102_126_MainActivity_stringFromJNI(
        JNIEnv *env,
        jobject jobj) {
    //一个结构体变量指针env对应当前的一个线程,获取当前的jvm;把虚拟机与env进行绑定
    //参数为指针变量的指针
    env->GetJavaVM(&j_vm);
//    获得实例对应的class类
    jclass cls = env->GetObjectClass(jobj);
    //V要大写
    callBack = env->GetMethodID(cls, "temp", "()V");
    //将当前的对象定义为全局的引用
    jobject obj = env->NewGlobalRef(jobj);
    //开启新的线程
    //四个参数:1,线程id的地址;
    // 2,表明我们的运行环境(是android还是其他的什么);NULL表示当前运行环境
    //3,新县城调用的方法;4,被调用的方法需要的参数
    pthread_create(&new_thread, NULL, run, obj);
    std::string hello = "Hello from C++";
    return env->NewStringUTF(hello.c_str());
}

void *run(void *obj) {
    //记录new_env的状态值
     int status;
     //创建一个新的环境变量(env是先前的环境)
     JNIEnv* new_env;//新的环境变量,和新的线程绑定
    //标记线程的状态
    bool isAttach = false;
    //验证new_env是不是一个有效的指针
    //如果不是有效的,将指针绑定到当前的虚拟机上,如果已经绑定,则忽略
    status=j_vm->GetEnv((void **) &new_env, JNI_VERSION_1_6);
    if(status<0){
        //将当前线程依附到当前的虚拟机上
        status=j_vm->AttachCurrentThread(&new_env,NULL);
        if(status<0){
            //依附失败
            return NULL;
        }
        isAttach=true;
    }
    //执行当前线程需要做的事情
    new_env->CallVoidMethod((jobject) obj, callBack);
    if(isAttach){
        //解除线程的绑定,成对出现
        j_vm->DetachCurrentThread();
        return NULL;
    }
}

看下运行结果

02-26 19:51:17.293 3434-3434/com.example.acer.test_18_02_26 I/System.out: 张欣念我一生一世main
02-26 19:51:17.301 3434-3448/com.example.acer.test_18_02_26 I/System.out: 张欣念我一生一世Thread-176

说明MainActivity里的temp方法调用了,两个线程不是同一个线程
二:JNI_OnLoad我也没搞明白,暂时不更新了

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值