程序之間通信方式
(1) 管道(PIPE)
(2) 命名管道(FIFO)
(3) 信号量(Semphore)
(4) 消息隊列(MessageQueue)
(5) 共享記憶體(SharedMemory)
(6) Socket
Java如何支援程序間通信。我們把Java程序了解為JVM程序。很明顯,傳統的這些大部分技術是無法被我們的應用程式利用了(這些程序間通信都是靠系統調用來實作的)。但是Java也有很多方法可以進行程序間通信的。
除了上面提到的Socket之外,當然首選的IPC(程序間通信)可以使用Rmi(遠端方法調用),或者Corba公共對象請求代理體系結構,通用對象請求代理體系結構)也可以。另外Java nio的MappedByteBuffer也可以通過記憶體映射檔案來實作程序間通信(共享記憶體)。
Java程序間通信可以采用的辦法:
Socket/RMI/WEBService/WebServer, 這些都可以實作直接的資料交換
Database/File, 這些可以實作間接的資料交換
看你的業務是否要求實時, 如果不需要, 用資料庫交換比較簡單
線程間通信:
可以直接傳入共享的變量來實作。
一看到 java NIO 的記憶體映射檔案(MappedByteBuffer),讓我立即就聯想到 Windows 系統的記憶體映射檔案。Windows 系統的記憶體映射檔案能用來在多個程序間共享資料,即程序間的共享記憶體,是通過把同一塊記憶體區域映射到不同程序的位址空間中,進而達到共享記憶體。
Java NIO 的記憶體映射檔案和 Windows 系統下的一樣,都能把實體檔案的内容映射到記憶體中,那麼 MappedByteBuffer 是否能用來在不同 Java 程序(JVM) 間共享資料呢?答案是肯定的,這樣在通常的 Socket 方式來實作 Java 程序間通信之上又多了一種方法。
在 Windows 中記憶體映射檔案可以是脫離實體檔案而存在的一塊命名的記憶體區域,使用相同的記憶體映射名就能在不同的程序中共享同一片記憶體。然後,Java 的 MappedByteBuffer 總是與某個實體檔案相關的,因為不管你是從 FileInputStream、FileOutputStream 還是 RandomAccessFile 得來的 FileChannel,再 map() 得到的記憶體映射檔案 MappedByteBuffer,如果在構造 FileInputStream、FileOutputStream、RandomAccessFile 對象時不指定實體檔案便會有 FileNotFoundException 異常。
是以 Java NIO 來實作共享記憶體的辦法就是讓不同程序的記憶體映射檔案關聯到同一個實體檔案,因為 MappedByteBuffer 能讓記憶體與檔案即時的同步内容。嚴格說來,稱之為記憶體共享是不準确的,其實就是兩個 Java 程序通過中間檔案來交換資料,用中間檔案使得兩個程序的兩塊記憶體區域的内容得到及時的同步。
用圖來了解 Java NIO 的“共享記憶體”的實作原理:
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiInBnauUmchh2ct0WZt9CXzJXZoR3bvw1ay92dl1WYyZ2LcRXZu9VY2Fman9Gbi9CXzV2Zh1WavwFdl5mLhZXYqd2bsJmL3d3dvw1LcpDc0RHaiojIsJye.jpg)
知道了實作原理之後,下面用代碼來示範兩個程序間用記憶體映射檔案來進行資料通信。代碼 WriteShareMemory.java 往映射檔案中依次寫入 A、B、C ... Z,ReadShareMemory.java 逐個讀出來,列印到螢幕上。代碼對交換檔案 swap.mm 的第一個位元組作了讀寫标志,分别是 0-可讀,1-正在寫,2-可讀。RandomAccessFile 得到的 Channel 能夠靈活的進行讀或寫,并且不會破壞原有檔案内容,而 FileInputStream 或 FileOutputStream 取得的 Channel 則很難達到這一功效,是以使用了 RandomAccessFile 來獲得 FileChannel。
WriteShareMemory.java
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | |
本文原始連結 http://unmi.cc/java-nio-memory-mapping-communicate/, 來自 隔葉黃莺 Unmi Blog
ReadShareMemory.java
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | |
在 Eclipse 中運作 WriteShareMemory,然後到指令行下運作 ReadShareMemory,你将會看到 WriteShareMemory 寫一個字元,ReadShareMemory 讀一個。
代碼中使用了讀寫标志位,和寫入的索引位置,是以在 WriteShareMemory 寫入一個字元後,隻有等待 ReadShareMemory 讀出剛寫入的字元後才會寫入第二個字元。實際應用中可以加入更好的通知方式,如檔案鎖等。
你也可以檢視執行時 c:\swap.mm 檔案的内容來驗證這一過程,因為 MappedByteBuffer 在運作時是一種 DirectByteBuffer,是以它能與檔案即時的同步内容,無須通過 FileChannel 來 write(buffer) 往檔案中手工寫入資料,或 read(buffer) 手工讀資料到記憶體中。
線程之間通信方式
TODO