生產(chǎn)者消費(fèi)者模型
基于生產(chǎn)者和消費(fèi)者的模型在編程中運(yùn)用是較多。生產(chǎn)者是一個(gè)或者多個(gè)線程產(chǎn)生數(shù)據(jù),消費(fèi)者是另一個(gè)或者多個(gè)線程處理數(shù)據(jù)桑阶,內(nèi)存緩沖區(qū)可以使用集合數(shù)組隊(duì)列方式,主要是用來協(xié)調(diào)生產(chǎn)者和消費(fèi)者之間的數(shù)據(jù)產(chǎn)生和消費(fèi)平衡宛琅。關(guān)鍵是如何處理多線程之間的協(xié)作。
在這個(gè)模型中逗旁,內(nèi)存緩沖區(qū)為空的時(shí)候消費(fèi)者處于等待狀態(tài)待生產(chǎn)者喚醒嘿辟,當(dāng)內(nèi)存緩沖區(qū)滿的時(shí)候,生產(chǎn)者處于等待狀態(tài)待消費(fèi)者喚醒片效。當(dāng)內(nèi)存緩沖區(qū)有產(chǎn)品沒有達(dá)到最大容量時(shí)生產(chǎn)者和消費(fèi)者是處于一個(gè)動(dòng)態(tài)平衡狀態(tài)红伦。設(shè)計(jì)到多線程,保證數(shù)據(jù)的正確新所以就需要鎖來保證淀衣。
#include <jni.h>
#include <string>
#include <pthread.h>
#include <android/log.h>
#include <queue>
#include <unistd.h>
pthread_t product_thread, consumer_thread;
pthread_mutex_t mutex;
pthread_cond_t condition;
std::queue<int> product_queue;
bool is_exit = false;
/**
*生產(chǎn)者
*/
void *product(void *arg) {
__android_log_print(ANDROID_LOG_ERROR, "thread_demo", "%s", (char *) arg);
while (!is_exit) {
//加鎖
pthread_mutex_lock(&mutex);
product_queue.push(1);
__android_log_print(ANDROID_LOG_ERROR, "thread_demo", "生產(chǎn)者生產(chǎn)產(chǎn)品%d", product_queue.size());
//通知消費(fèi)者消費(fèi)
pthread_cond_signal(&condition);
//釋放鎖
pthread_mutex_unlock(&mutex);
sleep(2);
}
return NULL;
}
/**
*消費(fèi)者
*/
void *consumer(void *arg) {
__android_log_print(ANDROID_LOG_ERROR, "thread_demo", "%s", (char *) arg);
while (!is_exit) {
pthread_mutex_lock(&mutex);
if (!product_queue.empty()) {
product_queue.pop();
__android_log_print(ANDROID_LOG_ERROR, "thread_demo", "消費(fèi)者消費(fèi)產(chǎn)品%d", product_queue.size());
} else{
//等待生產(chǎn)者 阻塞 會(huì)把鎖釋放
__android_log_print(ANDROID_LOG_ERROR, "thread_demo", "消費(fèi)者%s","等待生產(chǎn)者生產(chǎn)產(chǎn)品");
pthread_cond_wait(&condition, &mutex);
}
pthread_mutex_unlock(&mutex);
usleep(1000 * 500);
}
return NULL;
}
/**
* 生產(chǎn)者 消費(fèi)者
*/
extern "C"
JNIEXPORT void JNICALL
Java_com_youyangbo_thread_MainActivity_productConsumer(JNIEnv *env, jobject instance) {
int i = 0;
for (; i < 10; ++i) {
product_queue.push(i);
}
//初始化鎖
pthread_mutex_init(&mutex, NULL);
//初始化條件
pthread_cond_init(&condition, NULL);
//創(chuàng)建線程
pthread_create(&product_thread, NULL, product, (void *) "product");
pthread_create(&consumer_thread, NULL, consumer, (void *) "consumer");
//阻塞等待線程完畢
pthread_join(product_thread, NULL);
pthread_join(consumer_thread, NULL);
}
C/C++子線程調(diào)用java方法
C/C++與java之間的互相調(diào)用是要通過JNI來實(shí)現(xiàn)的昙读,JNIEnv是與線程之間有關(guān)系的,不同的線程JNIEnv是不同的膨桥,當(dāng)我們?cè)赾/c++層創(chuàng)建一個(gè)子線程要用到JNIEnv蛮浑,這個(gè)子線程的JNIEnv如何得到呢唠叛?獲取到JavaVM 然后通過JavaVM 調(diào)用AttachCurrentThread(JNIEnv** p_env, void* thr_args)來的到JNIEnv。JavaVM 怎么得到呢沮稚?在java調(diào)用native方法是會(huì)先執(zhí)行JNI_OnLoad(JavaVM* vm, void* reserved),還需要注意一個(gè)細(xì)節(jié)就是獲取MethodID不能夠在子線程獲取玻墅。需要放在主線程,創(chuàng)建 instance參數(shù)所引用對(duì)象的新全局引用 obj = env->NewGlobalRef(instance);
public class MainActivity extends AppCompatActivity {
static {
System.loadLibrary("native-lib");
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
callLog();
}
public native void callLog();
public void loge() {
Log.e( "loge: ", "被c++子線程調(diào)用了");
}
}
#include <jni.h>
#include <string>
#include <pthread.h>
#include <android/log.h>
JavaVM *java_vm;
jmethodID jmid;
jobject obj;
void *thread_callBack(void *arg) {
JNIEnv *env;
java_vm->AttachCurrentThread(&env, NULL);
if (!obj){
pthread_exit(0);
}
env->CallVoidMethod(obj, jmid);
java_vm->DetachCurrentThread();
return NULL;
}
extern "C"
JNIEXPORT void JNICALL
Java_com_youyangbo_thread_MainActivity_callLog(JNIEnv *env, jobject instance) {
obj = env->NewGlobalRef(instance);
jclass clz = env->GetObjectClass(obj);
jmid = env->GetMethodID(clz, "loge", "()V");
pthread_t pthread;
pthread_create(&pthread, NULL, thread_callBack, NULL);
pthread_join(pthread, NULL);
env->DeleteGlobalRef(obj);
}
extern "C"
JNIEXPORT jint JNICALL
JNI_OnLoad(JavaVM *vm, void *reserved) {
JNIEnv *env;
java_vm = vm;
if (vm->GetEnv((void **) &env, JNI_VERSION_1_6) != JNI_OK) {
return -1;
}
return JNI_VERSION_1_6;
}