<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

    共享內存在java中的實現 

    1、共享內存對應應用開發的意義 

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

    ◆讀寫操作的進程在執行讀寫操作時其他進程不能進行寫操作;

    ◆多個進程可以交替對某一共享內存執行寫操作;

    ◆一個進程執行了內存的寫操作后,不影響其他進程對該內存的訪問。同時其他進程對更新后的內存具有可見性; ◆在進程執行寫操作時如果異常退出,對其他進程寫操作禁止應自動解除;

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

    另外,共享內存的使用上有如下情況:
    ◆獨占的寫操作,相應有獨占的寫操作等待隊列。獨占的寫操作本身不會發生數據的一致性問題。

    ◆共享的寫操作,相應有共享的寫操作等待隊列。共享的寫操作則要注意防止發生數據的一致性問題。

    ◆獨占的讀操作,相應有共享的讀操作等待隊列。

    ◆共享的讀操作,相應有共享的讀操作等待隊列。
    一般情況下,我們只是關心第一二種情況。


    2、共享內存在java中的實現 

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

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

        如果多個應用映像同一文件名的共享內存,則意味著這多個應用共享了同一內存數據。這些應用對于文件可以具有同等存取權限,一個應用對數據的刷新會更新到多個應用中。
    為了防止多個應用同時對共享內存進行寫操作,可以在該共享內存的頭部信息加入寫操作標志。該共享內存的頭部基本信息至少有:

    int Length; // 共享內存的長度。
    int mode; // 該共享內存目前的存取模式。

        共享內存的頭部信息是類的私有信息,在多個應用可以對同一共享內存執行寫操作時,開始執行寫操作和結束寫操作時,需調用如下方法:

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

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

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

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



    Author: orangelizq
    email: orangelizq@163.com

    歡迎大家訪問我的個人網站 萌萌的IT人
    posted on 2009-05-13 16:08 桔子汁 閱讀(457) 評論(0)  編輯  收藏 所屬分類: J2SE
    主站蜘蛛池模板: 午夜视频在线观看免费完整版| 国产成人免费全部网站| 亚洲国语精品自产拍在线观看| 热99RE久久精品这里都是精品免费| 久久精品国产亚洲沈樵| 四虎成人精品永久免费AV| 亚洲国产电影在线观看| 日韩视频在线免费| 日韩免费一区二区三区在线| 国产亚洲中文日本不卡二区| 免费毛片在线视频| 又粗又大又黑又长的免费视频| 99热亚洲色精品国产88| 国产a级特黄的片子视频免费| 国产免费福利体检区久久| 亚洲一区二区三区日本久久九| 日韩精品成人无码专区免费| 日韩欧美亚洲国产精品字幕久久久| 国产啪亚洲国产精品无码| 30岁的女人韩剧免费观看| 无码色偷偷亚洲国内自拍| 亚洲成亚洲乱码一二三四区软件| 四虎在线成人免费网站| 在线亚洲精品视频| 色网站在线免费观看| 久久精品国产亚洲av影院| 日本免费中文字幕在线看| 久久免费观看国产99精品| 亚洲一区精彩视频| 亚洲伦理中文字幕| 亚洲激情视频图片| 亚洲综合久久精品无码色欲| 亚洲国产成人久久笫一页| 99精品视频在线视频免费观看| 亚洲成人动漫在线观看| 亚洲伊人成无码综合网| 无人在线直播免费观看| 黄色一级视频免费观看| 亚洲国产精品成人综合色在线婷婷| 亚洲第一区精品日韩在线播放| 最好看最新的中文字幕免费|