java消息隊(duì)列代碼示例,消息隊(duì)列代碼怎么寫(xiě)

如何用JAVA實(shí)現(xiàn)Linux上的消息隊(duì)列功能

下面來(lái)說(shuō)說(shuō)如何用不用消息隊(duì)列來(lái)進(jìn)行進(jìn)程間的通信,消息隊(duì)列與命名管道有很多相似之處。有關(guān)命名管道的更多內(nèi)容可以參閱我的另一篇文章:Linux進(jìn)程間通信——使用命名管道

成都網(wǎng)站建設(shè)哪家好,找成都創(chuàng)新互聯(lián)公司!專注于網(wǎng)頁(yè)設(shè)計(jì)、成都網(wǎng)站建設(shè)、微信開(kāi)發(fā)、成都小程序開(kāi)發(fā)、集團(tuán)成都企業(yè)網(wǎng)站建設(shè)等服務(wù)項(xiàng)目。核心團(tuán)隊(duì)均擁有互聯(lián)網(wǎng)行業(yè)多年經(jīng)驗(yàn),服務(wù)眾多知名企業(yè)客戶;涵蓋的客戶類型包括:成都砂巖浮雕等眾多領(lǐng)域,積累了大量豐富的經(jīng)驗(yàn),同時(shí)也獲得了客戶的一致稱贊!

一、什么是消息隊(duì)列

消息隊(duì)列提供了一種從一個(gè)進(jìn)程向另一個(gè)進(jìn)程發(fā)送一個(gè)數(shù)據(jù)塊的方法。 每個(gè)數(shù)據(jù)塊都被認(rèn)為含有一個(gè)類型,接收進(jìn)程可以獨(dú)立地接收含有不同類型的數(shù)據(jù)結(jié)構(gòu)。我們可以通過(guò)發(fā)送消息來(lái)避免命名管道的同步和阻塞問(wèn)題。但是消息隊(duì)列與命名管道一樣,每個(gè)數(shù)據(jù)塊都有一個(gè)最大長(zhǎng)度的限制。

Linux用宏MSGMAX和MSGMNB來(lái)限制一條消息的最大長(zhǎng)度和一個(gè)隊(duì)列的最大長(zhǎng)度。

二、在Linux中使用消息隊(duì)列

Linux提供了一系列消息隊(duì)列的函數(shù)接口來(lái)讓我們方便地使用它來(lái)實(shí)現(xiàn)進(jìn)程間的通信。它的用法與其他兩個(gè)System V PIC機(jī)制,即信號(hào)量和共享內(nèi)存相似。

1、msgget函數(shù)

該函數(shù)用來(lái)創(chuàng)建和訪問(wèn)一個(gè)消息隊(duì)列。它的原型為:

int msgget(key_t, key, int msgflg);

與其他的IPC機(jī)制一樣,程序必須提供一個(gè)鍵來(lái)命名某個(gè)特定的消息隊(duì)列。msgflg是一個(gè)權(quán)限標(biāo)志,表示消息隊(duì)列的訪問(wèn)權(quán)限,它與文件的訪問(wèn)權(quán)限一樣。msgflg可以與IPC_CREAT做或操作,表示當(dāng)key所命名的消息隊(duì)列不存在時(shí)創(chuàng)建一個(gè)消息隊(duì)列,如果key所命名的消息隊(duì)列存在時(shí),IPC_CREAT標(biāo)志會(huì)被忽略,而只返回一個(gè)標(biāo)識(shí)符。

它返回一個(gè)以key命名的消息隊(duì)列的標(biāo)識(shí)符(非零整數(shù)),失敗時(shí)返回-1.

2、msgsnd函數(shù)

該函數(shù)用來(lái)把消息添加到消息隊(duì)列中。它的原型為:

int msgsend(int msgid, const void *msg_ptr, size_t msg_sz, int msgflg);

msgid是由msgget函數(shù)返回的消息隊(duì)列標(biāo)識(shí)符。

msg_ptr是一個(gè)指向準(zhǔn)備發(fā)送消息的指針,但是消息的數(shù)據(jù)結(jié)構(gòu)卻有一定的要求,指針msg_ptr所指向的消息結(jié)構(gòu)一定要是以一個(gè)長(zhǎng)整型成員變量開(kāi)始的結(jié)構(gòu)體,接收函數(shù)將用這個(gè)成員來(lái)確定消息的類型。所以消息結(jié)構(gòu)要定義成這樣:

struct my_message{

long int message_type;

/* The data you wish to transfer*/

};

msg_sz是msg_ptr指向的消息的長(zhǎng)度,注意是消息的長(zhǎng)度,而不是整個(gè)結(jié)構(gòu)體的長(zhǎng)度,也就是說(shuō)msg_sz是不包括長(zhǎng)整型消息類型成員變量的長(zhǎng)度。

msgflg用于控制當(dāng)前消息隊(duì)列滿或隊(duì)列消息到達(dá)系統(tǒng)范圍的限制時(shí)將要發(fā)生的事情。

如果調(diào)用成功,消息數(shù)據(jù)的一分副本將被放到消息隊(duì)列中,并返回0,失敗時(shí)返回-1.

3、msgrcv函數(shù)

該函數(shù)用來(lái)從一個(gè)消息隊(duì)列獲取消息,它的原型為

int msgrcv(int msgid, void *msg_ptr, size_t msg_st, long int msgtype, int msgflg);

msgid, msg_ptr, msg_st的作用也函數(shù)msgsnd函數(shù)的一樣。

msgtype可以實(shí)現(xiàn)一種簡(jiǎn)單的接收優(yōu)先級(jí)。如果msgtype為0,就獲取隊(duì)列中的第一個(gè)消息。如果它的值大于零,將獲取具有相同消息類型的第一個(gè)信息。如果它小于零,就獲取類型等于或小于msgtype的絕對(duì)值的第一個(gè)消息。

msgflg用于控制當(dāng)隊(duì)列中沒(méi)有相應(yīng)類型的消息可以接收時(shí)將發(fā)生的事情。

調(diào)用成功時(shí),該函數(shù)返回放到接收緩存區(qū)中的字節(jié)數(shù),消息被復(fù)制到由msg_ptr指向的用戶分配的緩存區(qū)中,然后刪除消息隊(duì)列中的對(duì)應(yīng)消息。失敗時(shí)返回-1.

4、msgctl函數(shù)

該函數(shù)用來(lái)控制消息隊(duì)列,它與共享內(nèi)存的shmctl函數(shù)相似,它的原型為:

int msgctl(int msgid, int command, struct msgid_ds *buf);

command是將要采取的動(dòng)作,它可以取3個(gè)值,

IPC_STAT:把msgid_ds結(jié)構(gòu)中的數(shù)據(jù)設(shè)置為消息隊(duì)列的當(dāng)前關(guān)聯(lián)值,即用消息隊(duì)列的當(dāng)前關(guān)聯(lián)值覆蓋msgid_ds的值。

IPC_SET:如果進(jìn)程有足夠的權(quán)限,就把消息列隊(duì)的當(dāng)前關(guān)聯(lián)值設(shè)置為msgid_ds結(jié)構(gòu)中給出的值

IPC_RMID:刪除消息隊(duì)列

buf是指向msgid_ds結(jié)構(gòu)的指針,它指向消息隊(duì)列模式和訪問(wèn)權(quán)限的結(jié)構(gòu)。msgid_ds結(jié)構(gòu)至少包括以下成員:

struct msgid_ds

{

uid_t shm_perm.uid;

uid_t shm_perm.gid;

mode_t shm_perm.mode;

};

成功時(shí)返回0,失敗時(shí)返回-1.

三、使用消息隊(duì)列進(jìn)行進(jìn)程間通信

馬不停蹄,介紹完消息隊(duì)列的定義和可使用的接口之后,我們來(lái)看看它是怎么讓進(jìn)程進(jìn)行通信的。由于可以讓不相關(guān)的進(jìn)程進(jìn)行行通信,所以我們?cè)谶@里將會(huì)編寫(xiě)兩個(gè)程序,msgreceive和msgsned來(lái)表示接收和發(fā)送信息。根據(jù)正常的情況,我們?cè)试S兩個(gè)程序都可以創(chuàng)建消息,但只有接收者在接收完最后一個(gè)消息之后,它才把它刪除。

接收信息的程序源文件為msgreceive.c的源代碼為:

#include unistd.h

#include stdlib.h

#include stdio.h

#include string.h

#include errno.h

#include sys/msg.h

struct msg_st

{

long int msg_type;

char text[BUFSIZ];

};

int main()

{

int running = 1;

int msgid = -1;

struct msg_st data;

long int msgtype = 0; //注意1

//建立消息隊(duì)列

msgid = msgget((key_t)1234, 0666 | IPC_CREAT);

if(msgid == -1)

{

fprintf(stderr, "msgget failed with error: %d\n", errno);

exit(EXIT_FAILURE);

}

//從隊(duì)列中獲取消息,直到遇到end消息為止

while(running)

{

if(msgrcv(msgid, (void*)data, BUFSIZ, msgtype, 0) == -1)

{

fprintf(stderr, "msgrcv failed with errno: %d\n", errno);

exit(EXIT_FAILURE);

}

printf("You wrote: %s\n",data.text);

//遇到end結(jié)束

if(strncmp(data.text, "end", 3) == 0)

running = 0;

}

//刪除消息隊(duì)列

if(msgctl(msgid, IPC_RMID, 0) == -1)

{

fprintf(stderr, "msgctl(IPC_RMID) failed\n");

exit(EXIT_FAILURE);

}

exit(EXIT_SUCCESS);

}

發(fā)送信息的程序的源文件msgsend.c的源代碼為:

#include unistd.h

#include stdlib.h

#include stdio.h

#include string.h

#include sys/msg.h

#include errno.h

#define MAX_TEXT 512

struct msg_st

{

long int msg_type;

char text[MAX_TEXT];

};

int main()

{

int running = 1;

struct msg_st data;

char buffer[BUFSIZ];

int msgid = -1;

//建立消息隊(duì)列

msgid = msgget((key_t)1234, 0666 | IPC_CREAT);

if(msgid == -1)

{

fprintf(stderr, "msgget failed with error: %d\n", errno);

exit(EXIT_FAILURE);

}

//向消息隊(duì)列中寫(xiě)消息,直到寫(xiě)入end

while(running)

{

//輸入數(shù)據(jù)

printf("Enter some text: ");

fgets(buffer, BUFSIZ, stdin);

data.msg_type = 1; //注意2

strcpy(data.text, buffer);

//向隊(duì)列發(fā)送數(shù)據(jù)

if(msgsnd(msgid, (void*)data, MAX_TEXT, 0) == -1)

{

fprintf(stderr, "msgsnd failed\n");

exit(EXIT_FAILURE);

}

//輸入end結(jié)束輸入

if(strncmp(buffer, "end", 3) == 0)

running = 0;

sleep(1);

}

exit(EXIT_SUCCESS);

}

轉(zhuǎn)載僅供參考,版權(quán)屬于原作者。祝你愉快,滿意請(qǐng)采納哦

java,LinkedList實(shí)現(xiàn)的共享消息隊(duì)列,要求可以多線程調(diào)用,隨便謝謝思路就OK

public class Queue {

private LinkedListObject msgList = new LinkedListObject();

public Object getMsg() {

synchronized (this) {

if (msgList != null msgList.size() 0) {

return msgList.removeFirst();

}

return null;

}

}

public Object addMsg(Object obj) {

synchronized(this) {

msgList.addLast(obj);

}

return obj;

}

}

前幾天給別人寫(xiě)的,估計(jì)能實(shí)現(xiàn)你的要求的代碼,當(dāng)然沒(méi)寫(xiě)測(cè)試!

Java中關(guān)于如何實(shí)現(xiàn)多線程消息隊(duì)列的實(shí)例

java中的消息隊(duì)列

消息隊(duì)列是線程間通訊的手段:

import java.util.*

public class MsgQueue{

private Vector queue = null;

public MsgQueue(){

queue = new Vector();

}

public synchronized void send(Object o)

{

queue.addElement(o);

}

public synchronized Object recv()

{

if(queue.size()==0)

return null;

Object o = queue.firstElement();

queue.removeElementAt(0);//or queue[0] = null can also work

return o;

}

}

因?yàn)閖ava中是locked by object的所以添加synchronized 就可以用于線程同步鎖定對(duì)象

可以作為多線程處理多任務(wù)的存放task的隊(duì)列。他的client包括封裝好的task類以及thread類

Java的多線程-線程間的通信2009-08-25 21:58

1. 線程的幾種狀態(tài)

線程有四種狀態(tài),任何一個(gè)線程肯定處于這四種狀態(tài)中的一種:

1) 產(chǎn)生(New):線程對(duì)象已經(jīng)產(chǎn)生,但尚未被啟動(dòng),所以無(wú)法執(zhí)行。如通過(guò)new產(chǎn)生了一個(gè)線程對(duì)象后沒(méi)對(duì)它調(diào)用start()函數(shù)之前。

2) 可執(zhí)行(Runnable):每個(gè)支持多線程的系統(tǒng)都有一個(gè)排程器,排程器會(huì)從線程池中選擇一個(gè)線程并啟動(dòng)它。當(dāng)一個(gè)線程處于可執(zhí)行狀態(tài)時(shí),表示它可能正處于線程池中等待排排程器啟動(dòng)它;也可能它已正在執(zhí)行。如執(zhí)行了一個(gè)線程對(duì)象的start()方法后,線程就處于可執(zhí)行狀態(tài),但顯而易見(jiàn)的是此時(shí)線程不一定正在執(zhí)行中。

3) 死亡(Dead):當(dāng)一個(gè)線程正常結(jié)束,它便處于死亡狀態(tài)。如一個(gè)線程的run()函數(shù)執(zhí)行完畢后線程就進(jìn)入死亡狀態(tài)。

4) 停滯(Blocked):當(dāng)一個(gè)線程處于停滯狀態(tài)時(shí),系統(tǒng)排程器就會(huì)忽略它,不對(duì)它進(jìn)行排程。當(dāng)處于停滯狀態(tài)的線程重新回到可執(zhí)行狀態(tài)時(shí),它有可能重新執(zhí)行。如通過(guò)對(duì)一個(gè)線程調(diào)用wait()函數(shù)后,線程就進(jìn)入停滯狀態(tài),只有當(dāng)兩次對(duì)該線程調(diào)用notify或notifyAll后它才能兩次回到可執(zhí)行狀態(tài)。

2. class Thread下的常用函數(shù)函數(shù)

2.1 suspend()、resume()

1) 通過(guò)suspend()函數(shù),可使線程進(jìn)入停滯狀態(tài)。通過(guò)suspend()使線程進(jìn)入停滯狀態(tài)后,除非收到resume()消息,否則該線程不會(huì)變回可執(zhí)行狀態(tài)。

2) 當(dāng)調(diào)用suspend()函數(shù)后,線程不會(huì)釋放它的“鎖標(biāo)志”。

例11:

class TestThreadMethod extends Thread{

public static int shareVar = 0;

public TestThreadMethod(String name){

super(name);

}

public synchronized void run(){

if(shareVar==0){

for(int i=0; i5; i++){

shareVar++;

if(shareVar==5){

this.suspend(); //(1)

}}}

else{

System.out.print(Thread.currentThread().getName());

System.out.println(" shareVar = " + shareVar);

this.resume(); //(2)

}}

}

public class TestThread{

public static void main(String[] args){

TestThreadMethod t1 = new TestThreadMethod("t1");

TestThreadMethod t2 = new TestThreadMethod("t2");

t1.start(); //(5)

//t1.start(); //(3)

t2.start(); //(4)

}}

到底什么是消息隊(duì)列?Java中如何實(shí)現(xiàn)消息隊(duì)列

“消息隊(duì)列”是在消息的傳輸過(guò)程中保存消息的容器。和我們學(xué)過(guò)的LinkedHashMap,TreeSet等一樣,都是容器。既然是容器,就有有自己的特性,就像LinkedHashMap是以鍵值對(duì)存儲(chǔ)。存取順序不變。而消息隊(duì)列,看到隊(duì)列就可以知道。這個(gè)容器里面的消息是站好隊(duì)的,一般遵從先進(jìn)先出原則。

java中已經(jīng)為我們封裝好了很多的消息隊(duì)列。在java 1.5版本時(shí)推出的java.util.concurrent中有很多現(xiàn)成的隊(duì)列供我們使用。特性繁多,種類齊全。是你居家旅游開(kāi)發(fā)必備QAQ。

下面簡(jiǎn)單列舉這個(gè)包中的消息隊(duì)列

:阻塞隊(duì)列 BlockingQueue

數(shù)組阻塞隊(duì)列 ArrayBlockingQueue

延遲隊(duì)列 DelayQueue

鏈阻塞隊(duì)列 LinkedBlockingQueue

具有優(yōu)先級(jí)的阻塞隊(duì)列 PriorityBlockingQueue

同步隊(duì)列 SynchronousQueue

阻塞雙端隊(duì)列 BlockingDeque

鏈阻塞雙端隊(duì)列 LinkedBlockingDeque

不同的隊(duì)列不同的特性決定了隊(duì)列使用的時(shí)機(jī),感興趣的話你可以詳細(xì)了解。具體的使用方式我就不贅述了

網(wǎng)站名稱:java消息隊(duì)列代碼示例,消息隊(duì)列代碼怎么寫(xiě)
本文來(lái)源:http://muchs.cn/article4/hcjgoe.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供電子商務(wù)、企業(yè)網(wǎng)站制作關(guān)鍵詞優(yōu)化、網(wǎng)站維護(hù)服務(wù)器托管、微信公眾號(hào)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

成都定制網(wǎng)站建設(shè)