<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    隨筆-128  評論-55  文章-5  trackbacks-0

    共享內(nèi)存在java中的實(shí)現(xiàn) 

    1、共享內(nèi)存對應(yīng)應(yīng)用開發(fā)的意義 

        對熟知unix系統(tǒng)應(yīng)用開發(fā)的程序員來說,ipc(interprocess communication)機(jī)制是非常熟悉的,ipc基本包括共享內(nèi)存、信號燈操作、消息隊(duì)列、信號處理等部分,是開發(fā)應(yīng)用中非常重要的必不可少的工具。其中共享內(nèi)存ipc機(jī)制的關(guān)鍵,對于數(shù)據(jù)共享、系統(tǒng)快速查詢、動態(tài)配置、減少資源耗費(fèi)等均有獨(dú)到的優(yōu)點(diǎn)。 
        對應(yīng)unix系統(tǒng)來說,共享內(nèi)存分為一般共享內(nèi)存和映像文件共享內(nèi)存兩種,而對應(yīng)windows,實(shí)際上只有映像文件共享內(nèi)存一種。所以java應(yīng)用中,也是只能創(chuàng)建映像文件共享內(nèi)存。 
        在java語言中,基本上沒有提及共享內(nèi)存這個(gè)概念,但是,在某一些應(yīng)用中,共享內(nèi)存確實(shí)非常有用,例如采用java語言的分布式應(yīng)用系統(tǒng)中,存在著大量的分布式共享對象,很多時(shí)候需要查詢這些對象的狀態(tài),以查看系統(tǒng)是否運(yùn)行正常或者了解這些對象的目前的一些統(tǒng)計(jì)數(shù)據(jù)和狀態(tài)。如果采用網(wǎng)絡(luò)通信的方式,顯然會增加應(yīng)用的額外負(fù)擔(dān),也增加了一些不必要的應(yīng)用編程。而如果采用共享內(nèi)存的方式,則可以直接通過共享內(nèi)存查看對象的狀態(tài)數(shù)據(jù)和統(tǒng)計(jì)數(shù)據(jù),從而減少了一些不必要的麻煩。
    共享內(nèi)存的使用有如下幾個(gè)特點(diǎn):
    ◆可以被多個(gè)進(jìn)程打開訪問;

    ◆讀寫操作的進(jìn)程在執(zhí)行讀寫操作時(shí)其他進(jìn)程不能進(jìn)行寫操作;

    ◆多個(gè)進(jìn)程可以交替對某一共享內(nèi)存執(zhí)行寫操作;

    ◆一個(gè)進(jìn)程執(zhí)行了內(nèi)存的寫操作后,不影響其他進(jìn)程對該內(nèi)存的訪問。同時(shí)其他進(jìn)程對更新后的內(nèi)存具有可見性; ◆在進(jìn)程執(zhí)行寫操作時(shí)如果異常退出,對其他進(jìn)程寫操作禁止應(yīng)自動解除;

    ◆相對共享文件,數(shù)據(jù)訪問的方便性和效率。

    另外,共享內(nèi)存的使用上有如下情況:
    ◆獨(dú)占的寫操作,相應(yīng)有獨(dú)占的寫操作等待隊(duì)列。獨(dú)占的寫操作本身不會發(fā)生數(shù)據(jù)的一致性問題。

    ◆共享的寫操作,相應(yīng)有共享的寫操作等待隊(duì)列。共享的寫操作則要注意防止發(fā)生數(shù)據(jù)的一致性問題。

    ◆獨(dú)占的讀操作,相應(yīng)有共享的讀操作等待隊(duì)列。

    ◆共享的讀操作,相應(yīng)有共享的讀操作等待隊(duì)列。
    一般情況下,我們只是關(guān)心第一二種情況。


    2、共享內(nèi)存在java中的實(shí)現(xiàn) 

        在jdk1.4中提供的類MappedByteBuffer為我們實(shí)現(xiàn)共享內(nèi)存提供了較好的方法。該緩沖區(qū)實(shí)際上是一個(gè)磁盤文件的內(nèi)存映像。二者的變化將保持同步,即內(nèi)存數(shù)據(jù)發(fā)生變化會立刻反映到磁盤文件中,這樣會有效的保證共享內(nèi)存的實(shí)現(xiàn)。 
        將共享內(nèi)存和磁盤文件建立聯(lián)系的是文件通道類:FileChannel。該類的加入是JDK為了統(tǒng)一對外部設(shè)備(文件、網(wǎng)絡(luò)接口等)的訪問方法,并且加強(qiáng)了多線程對同一文件進(jìn)行存取的安全性。例如讀寫操作統(tǒng)一成read和write。這里只是用它來建立共享內(nèi)存用,它建立了共享內(nèi)存和磁盤文件之間的一個(gè)通道。
    打開一個(gè)文件建立一個(gè)文件通道可以用RandomAccessFile類中的方法getChannel。該方法將直接返回一個(gè)文件通道。該文件通道由于對應(yīng)的文件設(shè)為隨機(jī)存取文件,一方面可以進(jìn)行讀寫兩種操作,另一方面使用它不會破壞映像文件的內(nèi)容(如果用FileOutputStream直接打開一個(gè)映像文件會將該文件的大小置為0,當(dāng)然數(shù)據(jù)會全部丟失)。這里,如果用 FileOutputStream和FileInputStream則不能理想的實(shí)現(xiàn)共享內(nèi)存的要求,因?yàn)檫@兩個(gè)類同時(shí)實(shí)現(xiàn)自由的讀寫操作要困難得多。 
        下面的代碼實(shí)現(xiàn)了如上功能,它的作用類似UNIX系統(tǒng)中的mmap函數(shù)。

    // 獲得一個(gè)只讀的隨機(jī)存取文件對象
    RandomAccessFile RAFile = new RandomAccessFile(filename,"r");
    // 獲得相應(yīng)的文件通道
    FileChannel fc = RAFile.getChannel();
    // 取得文件的實(shí)際大小,以便映像到共享內(nèi)存
    int size = (int)fc.size();
    // 獲得共享內(nèi)存緩沖區(qū),該共享內(nèi)存只讀
    MappedByteBuffer mapBuf = fc.map(FileChannel.MAP_RO,0,size);
    // 獲得一個(gè)可讀寫的隨機(jī)存取文件對象
    RAFile = new RandomAccessFile(filename,"rw");
    // 獲得相應(yīng)的文件通道
    fc = RAFile.getChannel();
    // 取得文件的實(shí)際大小,以便映像到共享內(nèi)存
    size = (int)fc.size();
    // 獲得共享內(nèi)存緩沖區(qū),該共享內(nèi)存可讀寫
    mapBuf = fc.map(FileChannel.MAP_RW,0,size);
    // 獲取頭部消息:存取權(quán)限
    mode = mapBuf.getInt(); 

        如果多個(gè)應(yīng)用映像同一文件名的共享內(nèi)存,則意味著這多個(gè)應(yīng)用共享了同一內(nèi)存數(shù)據(jù)。這些應(yīng)用對于文件可以具有同等存取權(quán)限,一個(gè)應(yīng)用對數(shù)據(jù)的刷新會更新到多個(gè)應(yīng)用中。
    為了防止多個(gè)應(yīng)用同時(shí)對共享內(nèi)存進(jìn)行寫操作,可以在該共享內(nèi)存的頭部信息加入寫操作標(biāo)志。該共享內(nèi)存的頭部基本信息至少有:

    int Length; // 共享內(nèi)存的長度。
    int mode; // 該共享內(nèi)存目前的存取模式。

        共享內(nèi)存的頭部信息是類的私有信息,在多個(gè)應(yīng)用可以對同一共享內(nèi)存執(zhí)行寫操作時(shí),開始執(zhí)行寫操作和結(jié)束寫操作時(shí),需調(diào)用如下方法:

    public boolean StartWrite()
    {
    if(mode == 0) { // 標(biāo)志為0,則表示可寫
    mode = 1; // 置標(biāo)志為1,意味著別的應(yīng)用不可寫該共享內(nèi)存
    mapBuf.flip();
    mapBuf.putInt(mode); // 寫如共享內(nèi)存的頭部信息
    return true;
    }
    else {
    return false; // 指明已經(jīng)有應(yīng)用在寫該共享內(nèi)存,本應(yīng)用不可寫該共享內(nèi)存
    }
    }
    public boolean StopWrite()
    {
    mode = 0; // 釋放寫權(quán)限
    mapBuf.flip();
    mapBuf.putInt(mode); // 寫入共享內(nèi)存頭部信息
    return true;
    }

        這里提供的類文件mmap.java封裝了共享內(nèi)存的基本接口,讀者可以用該類擴(kuò)展成自己需要的功能全面的類。

        如果執(zhí)行寫操作的應(yīng)用異常中止,那么映像文件的共享內(nèi)存將不再能執(zhí)行寫操作。為了在應(yīng)用異常中止后,寫操作禁止標(biāo)志自動消除,必須讓運(yùn)行的應(yīng)用獲知退出的應(yīng)用。在多線程應(yīng)用中,可以用同步方法獲得這樣的效果,但是在多進(jìn)程中,同步是不起作用的。方法可以采用的多種技巧,這里只是描述一可能的實(shí)現(xiàn):采用文件鎖的方式。寫共享內(nèi)存應(yīng)用在獲得對一個(gè)共享內(nèi)存寫權(quán)限的時(shí)候,除了判斷頭部信息的寫權(quán)限標(biāo)志外,還要判斷一個(gè)臨時(shí)的鎖文件是否可以得到,如果可以得到,則即使頭部信息的寫權(quán)限標(biāo)志為1(上述),也可以啟動寫權(quán)限,其實(shí)這已經(jīng)表明寫權(quán)限獲得的應(yīng)用已經(jīng)異常退出,這段代碼如下:
     
    // 打開一個(gè)臨時(shí)的文件,注意同一共享內(nèi)存,該文件名要相同,可以在共享文件名后加后綴“.lock”。
    RandomAccessFile fis = new RandomAccessFile("shm.lock","rw");
    // 獲得文件通道
    FileChannel lockfc = fis.getChannel();
    // 獲得文件的獨(dú)占鎖,該方法不產(chǎn)生堵塞,立刻返回
    FileLock flock = lockfc.tryLock();
    // 如果為空,則表明已經(jīng)有應(yīng)用占有該鎖
    if(flock == null) {
    ...// 不能執(zhí)行寫操作
    }
    else {
    ...// 可以執(zhí)行寫操作
    }
    該鎖會在應(yīng)用異常退出后自動釋放,這正是該處所需要的方法。
     

    3、共享內(nèi)存在java中的應(yīng)用
    共享內(nèi)存在java應(yīng)用中,經(jīng)常有如下兩種種應(yīng)用:
    永久對象配置
    在java服務(wù)器應(yīng)用中,用戶可能會在運(yùn)行過程中配置一些參數(shù),而這些參數(shù)需要永久有效,當(dāng)服務(wù)器應(yīng)用重新啟動后,這些配置參數(shù)仍然可以對應(yīng)用起作用。這就可以用到該文中的共享內(nèi)存。該共享內(nèi)存中保存了服務(wù)器的運(yùn)行參數(shù)和一些對象運(yùn)行特性。可以在應(yīng)用啟動時(shí)讀入以啟用以前配置的參數(shù)。
    查詢共享數(shù)據(jù)
    一個(gè)應(yīng)用(例 sys.java)是系統(tǒng)的服務(wù)進(jìn)程,其系統(tǒng)的運(yùn)行狀態(tài)記錄在共享內(nèi)存中,其中運(yùn)行狀態(tài)可能是不斷變化的。為了隨時(shí)了解系統(tǒng)的運(yùn)行狀態(tài),啟動另一個(gè)應(yīng)用(例 mon.java),該應(yīng)用查詢該共享內(nèi)存,匯報(bào)系統(tǒng)的運(yùn)行狀態(tài)。
    可見,共享內(nèi)存在java應(yīng)用中還是很有用的,只要組織好共享內(nèi)存的數(shù)據(jù)結(jié)構(gòu),共享內(nèi)存就可以在應(yīng)用開發(fā)中發(fā)揮很不錯(cuò)的作用。
    本文來自學(xué)習(xí)網(wǎng)(www.gzu521.com),原文地址:http://www.gzu521.com/campus/article/program/200706/153343_2.htm



    Author: orangelizq
    email: orangelizq@163.com

    歡迎大家訪問我的個(gè)人網(wǎng)站 萌萌的IT人
    posted on 2009-05-13 16:08 桔子汁 閱讀(457) 評論(0)  編輯  收藏 所屬分類: J2SE
    主站蜘蛛池模板: 狼色精品人妻在线视频免费| 亚洲人成7777| 精品一区二区三区免费观看 | 亚洲熟妇色自偷自拍另类| 久久狠狠躁免费观看| 亚洲高清资源在线观看| 国产1000部成人免费视频| 亚洲一区在线视频| 青青青国产免费一夜七次郎| 亚洲av纯肉无码精品动漫| 四虎免费永久在线播放| 一道本在线免费视频| 亚洲夜夜欢A∨一区二区三区| 国产免费爽爽视频在线观看 | 亚洲熟女综合一区二区三区| 在线a毛片免费视频观看| 亚洲AV无码成人精品区日韩| 亚洲精品无码永久在线观看| 伊人久久大香线蕉免费视频| 亚洲综合精品香蕉久久网97| 中文字幕无码不卡免费视频| 激情小说亚洲图片| 亚洲精品乱码久久久久久自慰| 99re视频精品全部免费| 亚洲va久久久久| 亚洲熟伦熟女新五十路熟妇 | 国产亚洲福利精品一区二区| 久久久久亚洲?V成人无码| 免费精品99久久国产综合精品| 亚洲另类春色校园小说| 在线观看国产情趣免费视频 | 在线视频免费观看爽爽爽| 亚洲精品天堂成人片AV在线播放| 亚洲不卡AV影片在线播放| 久久这里只精品99re免费| 亚洲综合av一区二区三区不卡| 亚洲国产精品激情在线观看| 91老湿机福利免费体验| 亚洲AV无码专区国产乱码不卡| 亚洲国产精品福利片在线观看| 一级女人18毛片免费|