Linux生產(chǎn)者消費(fèi)者模型與C/C++子線程調(diào)用Java

生產(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;
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末壮虫,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子环础,更是在濱河造成了極大的恐慌囚似,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,277評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件线得,死亡現(xiàn)場離奇詭異饶唤,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)贯钩,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門募狂,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人角雷,你說我怎么就攤上這事祸穷。” “怎么了勺三?”我有些...
    開封第一講書人閱讀 163,624評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵雷滚,是天一觀的道長。 經(jīng)常有香客問我吗坚,道長祈远,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,356評(píng)論 1 293
  • 正文 為了忘掉前任商源,我火速辦了婚禮车份,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘牡彻。我一直安慰自己扫沼,他們只是感情好讨便,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,402評(píng)論 6 392
  • 文/花漫 我一把揭開白布充甚。 她就那樣靜靜地躺著,像睡著了一般霸褒。 火紅的嫁衣襯著肌膚如雪抖誉。 梳的紋絲不亂的頭發(fā)上樊零,一...
    開封第一講書人閱讀 51,292評(píng)論 1 301
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死巷屿,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的遍略。 我是一名探鬼主播纽绍,決...
    沈念sama閱讀 40,135評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼皆怕,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼愈腾!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起析二,我...
    開封第一講書人閱讀 38,992評(píng)論 0 275
  • 序言:老撾萬榮一對(duì)情侶失蹤安拟,失蹤者是張志新(化名)和其女友劉穎蛤吓,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體糠赦,經(jīng)...
    沈念sama閱讀 45,429評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡会傲,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,636評(píng)論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了拙泽。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片淌山。...
    茶點(diǎn)故事閱讀 39,785評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖顾瞻,靈堂內(nèi)的尸體忽然破棺而出泼疑,到底是詐尸還是另有隱情,我是刑警寧澤朋其,帶...
    沈念sama閱讀 35,492評(píng)論 5 345
  • 正文 年R本政府宣布王浴,位于F島的核電站脆炎,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏氓辣。R本人自食惡果不足惜秒裕,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,092評(píng)論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望钞啸。 院中可真熱鬧几蜻,春花似錦、人聲如沸体斩。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽絮吵。三九已至弧烤,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間蹬敲,已是汗流浹背暇昂。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評(píng)論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留伴嗡,地道東北人急波。 一個(gè)月前我還...
    沈念sama閱讀 47,891評(píng)論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像瘪校,于是被迫代替她去往敵國和親澄暮。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,713評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容