//// Created by Inke219223m on 2022/6/30.//#ifndefMEDIAANDROID_JNI_PRACTICE_H#defineMEDIAANDROID_JNI_PRACTICE_H#include<jni.h>#include<iostream>#include"LogUtils.h"#include"../CLog.h"#include"pthread.h"#include"unistd.h"#include"queue"
using namespace std;
class jni_practice {};extern"C"
JNIEXPORT void JNICALL Java_cn_com_codingce_mediaandroid_activity_jni_JniActivity_useJNICreateJavaObject(JNIEnv *, jobject, jint i, jstring thread_name, jobject inputAnimal);//1、一般线程//线程对象pthread_t pthread;void*threadDoThings(void*data){LOGD("jni thread do things");pthread_exit(&pthread);}//2、线程锁//产品队列,里面是int的队列
std::queue<int> queueInit;//生产者线程pthread_t pthread_produc;//消费者线程pthread_t pthread_customer;//线程锁pthread_mutex_t mutexInit;//条件对象pthread_cond_t cond;voidinitMutex();void*customerThread(void*data);void*ptoducThread(void*data);void*threadDoThings(void*data);#endif//MEDIAANDROID_JNI_PRACTICE_H
jni_practice.cpp
//// Created by Inke219223m on 2022/6/30.//#include"jni_practice.h"
using namespace std;extern"C"
JNIEXPORT void JNICALL
Java_cn_com_codingce_mediaandroid_activity_jni_JniActivity_useJNICreateJavaObject(JNIEnv
*env,
jobject thiz,
jint
i,
jstring threadName,
jobject inputAnimal){//外层线程信息constchar*threadNameWithC = env->GetStringUTFChars(threadName, JNI_FALSE);LOGE("线程Name: %s, %d", threadNameWithC, i)/// Java层传递对象处理 START //想要获取的字段 id
jfieldID fid;//字段对应的具体的值
jstring inputJstr;//将 Java 的字符串转换为 Native 的字符串constchar*str;//获取 Java class
jclass inputAnimalCls = env->GetObjectClass(inputAnimal);//获取对应字段的 id
fid = env->GetFieldID(inputAnimalCls,"name","Ljava/lang/String;");//如果字段为 NULL ,直接退出,查找失败if(fid == nullptr){return;}//获取字段对应的值
inputJstr =(jstring) env->GetObjectField(inputAnimal, fid);
str = env->GetStringUTFChars(inputJstr, nullptr);if(str == nullptr){return;}LOGD("input Object name is %s", str);/// Java层传递对象处理 END /// 创建对象 START //获取 animal 对应的 jlcass 对象
jclass animalClazz = env->FindClass("cn/com/codingce/mediaandroid/entity/Animal");//获取构造函数的 jmethodID
jmethodID animal_constructor = env->GetMethodID(animalClazz,"<init>","(Ljava/lang/String;I)V");
jstring name = env->NewStringUTF("INKE");//调用构造函数创建 animal 对象
jobject animal = env->NewObject(animalClazz, animal_constructor, name,20);/// 创建对象END /// 普通操作 START //类中方法//get 方法
jmethodID getName = env->GetMethodID(animalClazz,"getName","()Ljava/lang/String;");//获取 get 方法返回的 Nameauto jstringGetName =(jstring) env->CallObjectMethod(animal, getName);constchar*charName = env->GetStringUTFChars(jstringGetName, JNI_FALSE);//__android_log_print(ANDROID_LOG_INFO, "mmm", "method = %s, msg = %s", __FUNCTION__, charName);LOGE("Create Object Get name: %s", charName)//set 方法//新 Name
jstring nameMod = env->NewStringUTF("NewNameSetAchieve");//获取 set 方法
jmethodID setName = env->GetMethodID(animalClazz,"setName","(Ljava/lang/String;)V");
env->CallVoidMethod(animal, setName, nameMod
);//获取成员变量 name
jfieldID jfieldIdName = env->GetFieldID(animalClazz,"name","Ljava/lang/String;");//获取成员变量 name 的值auto jstr =(jstring) env->GetObjectField(animal, jfieldIdName);//jstring 转换成 charconstchar*charNameJstr = env->GetStringUTFChars(jstr, JNI_FALSE);LOGE("Get Object New Name: %s", charNameJstr)//获取成员变量
jfieldID jfieldIdAge = env->GetFieldID(animalClazz,"age","I");//获取成员变量 Age 的值
jint jintAge =(jint)
env->GetIntField(animal, jfieldIdAge
);LOGE("Get Object Age:%d", jintAge)/// 普通操作 END /// 静态操作 START //获取静态变量 num
jfieldID jfieldIdNum = env->GetStaticFieldID(animalClazz,"num","I");//获取静态变量 num 的值
jint num =(jint)
env->GetStaticIntField(animalClazz, jfieldIdNum
);
cout <<"获取静态变量 num 的值: "<<
num;//修改静态变量 num 的值
jint jint1 =2000;
env->SetStaticIntField(animalClazz, jfieldIdNum, jint1
);//获取静态方法 eat()
jmethodID jmethodId = env->GetStaticMethodID(animalClazz,"eat","()V");//调用静态方法 eat()
env->CallStaticVoidMethod(animalClazz, jmethodId
);
jint num1 =(jint)
env->GetStaticIntField(animalClazz, jfieldIdNum
);__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,"env->GetStaticIntField(animalClazz, jfieldIdNum): %d", num1);/// 静态操作 END /// 多线程 START //创建线程pthread_create(&pthread, nullptr, threadDoThings, nullptr
);//生产者消费者模型//初始化时,先往队列中添加10个产品// for (// int i = 0;// i < 10; i++) {// queueInit.push(i);// }//生产者消费者//initMutex();/// 多线程 END /// 资源释放 START ///// 引用型对象需要释放,包括 jstring, jclass, jobject, jbyteArray 等等;从作用域的角度分为两类:Global and Local References https://www.jianshu.com/p/c867e4abcb5f /////jstring
env->DeleteLocalRef(name);
env->DeleteLocalRef(jstringGetName);
env->DeleteLocalRef(nameMod);
env->DeleteLocalRef(jstr);
env->DeleteLocalRef(inputJstr);//jbyteArray//env->ReleaseByteArrayElements(imgdata, imgByte, 0);//jclass
env->DeleteLocalRef(animalClazz);//如果你要返回 animal 则不需要释放
env->DeleteLocalRef(animal);/// 资源释放 END //}void*ptoducThread(void*data){while(queueInit.size()<50){LOGD("生产者生产一个产品")//操作队列前先加锁pthread_mutex_lock(&mutexInit);
queueInit.push(1);if(queueInit.size()>0){LOGD("生产者通知消费者有产品产生,产品数量为:%d", queueInit.size());//有了产品通知消费者pthread_cond_signal(&cond);}//解锁线程pthread_mutex_unlock(&mutexInit);//休息4秒,单位是秒sleep(4);}pthread_exit(&pthread_produc);}voidinitMutex(){//初始化锁对象 对应pthread_mutex_destroy销毁锁对象pthread_mutex_init(&mutexInit, nullptr);//初始化条件变量 对应pthread_cond_destroy销毁条件变量pthread_cond_init(&cond, nullptr);//创建生产者线程,并传递参数pthread_create(&pthread_produc, nullptr, ptoducThread,(void*)"product");//创建消费者线程pthread_create(&pthread_customer, nullptr, customerThread, nullptr);}void*customerThread(void*data){char*prod =(char*) data;LOGD("%s", prod)//这里用死循环,时间情况应该给一个变量来控制跳出循环while(1){//操作队列前先加锁pthread_mutex_lock(&mutexInit);if(queueInit.size()>0){
queueInit.pop();LOGE("消费者消费一个产品,产品数量为:%d", queueInit.size());}else{LOGE("产品消费完了,等待生产者生产......");//阻塞线程等待生产者的通知pthread_cond_wait(&cond,&mutexInit);}//解锁线程pthread_mutex_unlock(&mutexInit);//休息0.5秒,usleep单位是微妙usleep(500*1000);}pthread_exit(&pthread_customer);}