`
coach
  • 浏览: 382893 次
  • 性别: Icon_minigender_2
  • 来自: 印度
社区版块
存档分类
最新评论

Java NIO 应用 -- 使用内存映射文件实现进程间通信

阅读更多
一看到 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 的“共享内存”的实现原理:


知道了实现原理之后,下面用代码来演示两个进程间用内存映射文件来进行数据通信。代码 WriteShareMemory.java 往映射文件中依次写入 A、B、C ... Z,ReadShareMemory.java 逐个读出来,打印到屏幕上。代码对交换文件 swap.mm 的第一个字节作了读写标志,分别是 0-可读,1-正在写,2-可读。RandomAccessFile 得到的 Channel 能够灵活的进行读或写,并且不会破坏原有文件内容,而 FileInputStream 或 FileOutputStream 取得的 Channel 则很难达到这一功效,所以使用了 RandomAccessFile 来获得 FileChannel。

WriteShareMemory.java
package com.unmi;

import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.FileChannel.MapMode;

/**
 * 往 "共享内存" 写入数据
 * @author Unmi
 */
public class WriteShareMemory {

	/**
	 * @param args
	 * @throws Exception 
	 */
	public static void main(String[] args) throws Exception {
		RandomAccessFile raf = new RandomAccessFile("c:/swap.mm", "rw");
		FileChannel fc = raf.getChannel();
		MappedByteBuffer mbb = fc.map(MapMode.READ_WRITE, 0, 1024);
		
		//清除文件内容
		for(int i=0;i<1024;i++){
			mbb.put(i,(byte)0);
		}
		
		//从文件的第二个字节开始,依次写入 A-Z 字母,第一个字节指明了当前操作的位置
		for(int i=65;i<91;i++){
			int index = i-63;
			int flag = mbb.get(0); //可读标置第一个字节为 0
			if(flag != 0){ //不是可写标示 0,则重复循环,等待
				i --;
				continue;
			}
			mbb.put(0,(byte)1); //正在写数据,标志第一个字节为 1
			mbb.put(1,(byte)(index)); //写数据的位置
			
			System.out.println("程序 WriteShareMemory:"+System.currentTimeMillis() + 
					":位置:" + index +" 写入数据:" + (char)i);
			
			mbb.put(index,(byte)i);//index 位置写入数据
			mbb.put(0,(byte)2); //置可读数据标志第一个字节为 2
			Thread.sleep(513);
		}
	}
}


ReadShareMemory.java
package com.unmi;

import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.FileChannel.MapMode;

/**
 * 从 "共享内存" 读出数据
 * @author Unmi
 */
public class ReadShareMemory {

	/**
	 * @param args
	 * @throws Exception 
	 */
	public static void main(String[] args) throws Exception {
		RandomAccessFile raf = new RandomAccessFile("c:/swap.mm", "rw");
		FileChannel fc = raf.getChannel();
		MappedByteBuffer mbb = fc.map(MapMode.READ_WRITE, 0, 1024);
		int lastIndex = 0;

		for(int i=1;i<27;i++){
			int flag = mbb.get(0); //取读写数据的标志
			int index = mbb.get(1); //读取数据的位置,2 为可读

			if(flag != 2 || index == lastIndex){ //假如不可读,或未写入新数据时重复循环
				i--;
				continue;
			}
			
			lastIndex = index;
			System.out.println("程序 ReadShareMemory:" + System.currentTimeMillis() + 
					":位置:" + index +" 读出数据:" + (char)mbb.get(index));
			
			mbb.put(0,(byte)0); //置第一个字节为可读标志为 0
			
			if(index == 27){ //读完数据后退出
				break;
			}
		}
	}
}


在 Eclipse 中运行 WriteShareMemory,然后到命令行下运行 ReadShareMemory,你将会看到 WriteShareMemory 写一个字符,ReadShareMemory 读一个。



代码中使用了读写标志位,和写入的索引位置,所以在 WriteShareMemory 写入一个字符后,只有等待 ReadShareMemory 读出刚写入的字符后才会写入第二个字符。实际应用中可以加入更好的通知方式,如文件锁等。

你也可以查看执行时 c:\swap.mm 文件的内容来验证这一过程,因为 MappedByteBuffer 在运行时是一种 DirectByteBuffer,所以它能与文件即时的同步内容,无须通过 FileChannel 来 write(buffer) 往文件中手工写入数据,或 read(buffer) 手工读数据到内存中。





分享到:
评论
2 楼 cectsky 2012-02-23  
性能是不是不高啊,毕竟要进行文件IO操作
1 楼 hjhnju 2010-10-20  
这种实现和使用文件锁来同步文件好像没什么太大区别?

相关推荐

    Java NIO 应用使用内存映射文件实现进程间通信

    Java NIO 应用 -- 使用内存映射文件实现进程间通信

    Java NIO实战开发多人聊天室

    13-Java NIO-Buffer-基本使用.mp4 14-Java NIO-Buffer-三个属性和类型.mp4 17-Java NIO-Buffer-缓冲区分片.mp4 18-Java NIO-Buffer-只读缓冲区.mp4 19-Java NIO-Buffer-直接缓冲区.mp4 21-Java NIO-Selector-概述....

    java网络编程NIO视频教程

    01-Java NIO-课程简介.mp4 02-Java NIO-概述.mp4 03-Java NIO-Channel-概述.mp4 ...13-Java NIO-Buffer-基本使用.mp4 14-Java NIO-Buffer-三个属性和类型.mp4 15-Java NIO-Buffer-分配和读写数据.mp4

    [第9节] Java NIO流-选择器操作4

    [第9节] Java NIO流-选择器操作4[第9节] Java NIO流-选择器操作4[第9节] Java NIO流-选择器操作4

    Java应用服务器Java-Nio-Services.zip

    JAVA服务器基于JAVA NIO I. 实现HTTP协议 II. 实现HTTPS协议 III. 实现FASTCGI协议(Client端) 运行HTTP/HTTPS服务器 运行开发包下jar文件 java -jar http-server-version-{version}.jar   ...

    Java-NIO-Programming-Cookbook(含源码)

    Java-NIO-Programming-Cookbook英文版和配套源代码。有一个使用DirectByteBuffer和Non-Direct Buffer文件读取速度的对比实验程序和测试结果。

    Java NIO 指南 - v1.0.pdf

    Java NIO(New IO)是一个可以替代标准 Java IO API 的 IO API(从 Java 1.4 开始),Java NIO 提供了与标准 IO 不同的 IO 工作方式。本教程讲解了 Java NIO 的三个核心组件,并介绍了跟核心组件相关的内容,旨在帮助 ...

    Java-NIO-Netty框架学习

    Java-NIO-Netty框架入门学习。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。

    java nio 包读取超大数据文件

    Java nio 超大数据文件 超大数据文件Java nio 超大数据文件 超大数据文件Java nio 超大数据文件 超大数据文件Java nio 超大数据文件 超大数据文件Java nio 超大数据文件 超大数据文件Java nio 超大数据文件 超大数据...

    java nio 实现socket

    java nio 实现socketjava nio 实现socketjava nio 实现socketjava nio 实现socketjava nio 实现socket

    httpcore-nio-4.4.6-API文档-中文版.zip

    赠送jar包:httpcore-nio-4.4.6.jar 赠送原API文档:httpcore-nio-4.4.6-javadoc.jar 赠送源代码:httpcore-nio-4.4.6-sources.jar 包含翻译后的API文档:httpcore-nio-4.4.6-javadoc-API文档-中文(简体)版.zip ...

    JAVA-NIO-DEMO

    Anontion、Applet、NIO等Demo,可以辅助理解一下相关知识点

    httpcore-nio-4.4.15-API文档-中文版.zip

    赠送jar包:httpcore-nio-4.4.15.jar 赠送原API文档:httpcore-nio-4.4.15-javadoc.jar 赠送源代码:httpcore-nio-4.4.15-sources.jar 包含翻译后的API文档:httpcore-nio-4.4.15-javadoc-API文档-中文(简体)版....

    httpcore-nio-4.4.10-API文档-中文版.zip

    赠送jar包:httpcore-nio-4.4.10.jar; 赠送原API文档:httpcore-nio-4.4.10-javadoc.jar; 赠送源代码:httpcore-nio-4.4.10-sources.jar; 赠送Maven依赖信息文件:httpcore-nio-4.4.10.pom; 包含翻译后的API文档...

    Java视频教程 Java游戏服务器端开发 Netty NIO AIO Mina视频教程

    三、Java语言基础教程-Java NIO流篇 [第1节] Java NIO流-简介和概述.flv [第2节] Java NIO流-缓冲区.flv [第3节] Java NIO流-缓冲区操作.flv [第4节] JavaNIO流-通道1.flv [第5节] Java NIO流-通道2.flv [第6...

    httpcore-nio-4.4.10-API文档-中英对照版.zip

    赠送jar包:httpcore-nio-4.4.10.jar; 赠送原API文档:httpcore-nio-4.4.10-javadoc.jar; 赠送源代码:httpcore-nio-4.4.10-sources.jar; 赠送Maven依赖信息文件:httpcore-nio-4.4.10.pom; 包含翻译后的API文档...

    java nio 读文件

    java nio 读文件,java nio 读文件

    httpcore-nio-4.4.15-API文档-中英对照版.zip

    赠送jar包:httpcore-nio-4.4.15.jar 赠送原API文档:httpcore-nio-4.4.15-javadoc.jar 赠送源代码:httpcore-nio-4.4.15-sources.jar 包含翻译后的API文档:httpcore-nio-4.4.15-javadoc-API文档-中文(简体)-...

    Java-NIO-系列教程

    Java-NIO-系列教程

    java基于NIO实现Reactor模型源码.zip

    java基于NIO实现Reactor模型源码java基于NIO实现Reactor模型源码java基于NIO实现Reactor模型源码java基于NIO实现Reactor模型源码java基于NIO实现Reactor模型源码java基于NIO实现Reactor模型源码java基于NIO实现...

Global site tag (gtag.js) - Google Analytics