`
毛驴追飞机
  • 浏览: 16355 次
  • 性别: Icon_minigender_1
  • 来自: 南京
社区版块
存档分类
最新评论

java实现共享内存操作

    博客分类:
  • java
阅读更多

 

    对UNIX系统来说,共享内存分为一般共享内存和映像文件共享内存两种,对windows实际上只有映像文件共享内存一种。所以java应用中也是只能创建映像文件共享内存。使用共享内存,有如下几个特点:

1、可以被多个进程打开访问。

2、读写操作的进程在执行读写操作时其他进程不能进行写操作。

3、多个进程可以交替对某一共享内存执行写操作。

4、一个进程执行了内存的写操作后,不影响其他进程对该内存的访问。同时其他进程对更新后的内存具有可见性。

5、在进程执行写操作时,如果异常退出,对其他进程写操作禁止应自动解除。

 

一般我们操作共享内存有以下几种情况,主要关注1,2:

1、独占的写操作,相应有独占的写操作等待队列。独占的写操作本身不会发生数据的一致性问题。

2、共享的写操作,相应有共享的写操作等待队列。共享的写操作哦则要注意防止发生数据的一致性问题。

3、独占的读操作,相应有共享的读操作等待队列。

4、共享的读操作,相应有共享的读操作等待队列。

 

在jdk1.4中提供的类MappedByteBuffer为我们提供了实现共享内存的方法,该缓冲区实际上是一个磁盘文件的内存映像。二者的变化保持同步,即内存数据发生变化会立刻反应到磁盘文件中,这样会有效的保证共享内存的实现。废话不多说,直接看代码:

package com.hx.sharemem;

import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;
import java.util.Properties;

import com.hx.util.FileUtil;


/**
 * 共享内存操作类
 * @author hx
 *
 */
public class ShareMemory {

	int flen = 41779264;					//开辟共享内存大小
	int fsize = 0;							//文件的实际大小
	String shareFileName;					//共享内存文件名
	String sharePath;						//共享内存路径
	MappedByteBuffer mapBuf = null;			//定义共享内存缓冲区
	FileChannel fc = null;					//定义相应的文件通道
	FileLock fl = null;						//定义文件区域锁定的标记。		
	Properties p = null;
	RandomAccessFile RAFile = null;			//定义一个随机存取文件对象

	/**
	 * 
	 * @param sp	共享内存文件路径
	 * @param sf	共享内存文件名
	 */
	public ShareMemory(String sp, String sf) {
		if (sp.length() != 0) {
			FileUtil.CreateDir(sp);
			this.sharePath = sp + File.separator;
		} else {
			this.sharePath = sp;
		}
		this.shareFileName = sf;

		try {
			// 获得一个只读的随机存取文件对象   "rw" 打开以便读取和写入。如果该文件尚不存在,则尝试创建该文件。  
			RAFile = new RandomAccessFile(this.sharePath + this.shareFileName + ".sm", "rw");
			//获取相应的文件通道
			fc = RAFile.getChannel();
			//获取实际文件的大小
			fsize = (int) fc.size();
			if (fsize < flen) {
				byte bb[] = new byte[flen - fsize];
				//创建字节缓冲区
				ByteBuffer bf = ByteBuffer.wrap(bb);
				bf.clear();
				//设置此通道的文件位置。 
				fc.position(fsize);
				//将字节序列从给定的缓冲区写入此通道。
				fc.write(bf);
				fc.force(false);

				fsize = flen;
			}
			//将此通道的文件区域直接映射到内存中。
			mapBuf = fc.map(FileChannel.MapMode.READ_WRITE, 0, fsize);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	/**
	 * 
	 * @param ps		锁定区域开始的位置;必须为非负数
	 * @param len		锁定区域的大小;必须为非负数
	 * @param buff		写入的数据
	 * @return
	 */
	public synchronized int write(int ps, int len, byte[] buff) {
		if (ps >= fsize || ps + len >= fsize) {
			return 0;
		}
		//定义文件区域锁定的标记。
		FileLock fl = null;
		try {
			//获取此通道的文件给定区域上的锁定。 
			fl = fc.lock(ps, len, false);
			if (fl != null) {

				mapBuf.position(ps);
				ByteBuffer bf1 = ByteBuffer.wrap(buff);
				mapBuf.put(bf1);
				//释放此锁定。
				fl.release();

				return len;
			}
		} catch (Exception e) {
			if (fl != null) {
				try {
					fl.release();
				} catch (IOException e1) {
					System.out.println(e1.toString());
				}
			}
			return 0;
		}

		return 0;
	}
	
	/**
	 * 
	 * @param ps		锁定区域开始的位置;必须为非负数
	 * @param len		锁定区域的大小;必须为非负数
	 * @param buff		要取的数据
	 * @return
	 */
	public synchronized int read(int ps, int len, byte[] buff) {
		if (ps >= fsize) {
			return 0;
		}
		//定义文件区域锁定的标记。
		FileLock fl = null;
		try {
			fl = fc.lock(ps, len, false);
			if (fl != null) {
				//System.out.println( "ps="+ps );
				mapBuf.position(ps);
				if (mapBuf.remaining() < len) {
					len = mapBuf.remaining();
				}

				if (len > 0) {
					mapBuf.get(buff, 0, len);
				}

				fl.release();

				return len;
			}
		} catch (Exception e) {
			if (fl != null) {
				try {
					fl.release();
				} catch (IOException e1) {
					System.out.println(e1.toString());
				}
			}
			return 0;
		}

		return 0;
	}
	
	/**
	 * 完成,关闭相关操作
	 */
	protected void finalize() throws Throwable {
		if (fc != null) {
			try {
				fc.close();
			} catch (IOException e) {
				System.out.println(e.toString());
			}
			fc = null;
		}

		if (RAFile != null) {
			try {
				RAFile.close();
			} catch (IOException e) {
				System.out.println(e.toString());
			}
			RAFile = null;
		}
		mapBuf = null;
	}
	
	/**
	 * 关闭共享内存操作
	 */
	public synchronized void closeSMFile() {
		if (fc != null) {
			try {
				fc.close();
			} catch (IOException e) {
				System.out.println(e.toString());
			}
			fc = null;
		}

		if (RAFile != null) {
			try {
				RAFile.close();
			} catch (IOException e) {
				System.out.println(e.toString());
			}
			RAFile = null;
		}
		mapBuf = null;
	}
	
	/**
	 *  检查退出
	 * @return	true-成功,false-失败
	 */
	public synchronized boolean checkToExit() {
		byte bb[] = new byte[1];

		if (read(1, 1, bb) > 0) {
			if (bb[0] == 1) {
				return true;

			}
		}

		return false;
	}

	/**
	 * 复位退出
	 */
	public synchronized void resetExit() {
		byte bb[] = new byte[1];

		bb[0] = 0;
		write(1, 1, bb);

	}

	/**
	 * 退出
	 */
	public synchronized void toExit() {
		byte bb[] = new byte[1];

		bb[0] = 1;
		write(1, 1, bb);

	}
	
	public static void main(String arsg[]) throws Exception{
		ShareMemory sm = new ShareMemory("E://demo","test");
		String str = "中文测试";
		sm.write(40, 20, str.getBytes("UTF-8"));
		byte[] b = new byte[20];
		sm.read(40, 20, b);
		System.out.println(new String(b,"UTF-8"));
	}
}

 

分享到:
评论

相关推荐

    JAVA实现Modbus RTU或Modbus TCPIP数据采集.rar

    2.多线程之间为更方便的实现数据共享采用了共享相同内存地址空间的形式,并且是并发运行,导致多个线程可能会同时访问或修改其他线程正在使用的变量值,导致安全性,同时如果线程之间相互等待对方拥有的锁,会出现...

    Java计算机操作系统实验

    实验二要求学生模拟作业调度的实现,用高级语言编写和调试多个作业调度的模拟程序,了解作业调度在操作系统中的作用,以加深对作业调度算法的理解。 实验三通过编写和调试存储管理的模拟程序以加深对存储管理方案的...

    java源码包---java 源码 大量 实例

     Java实现的FTP连接与数据浏览程序,实现实例化可操作的窗口。  部分源代码摘录:  ftpClient = new FtpClient(); //实例化FtpClient对象  String serverAddr=jtfServer.getText(); //得到服务器地址  ...

    java源码包4

     Java实现的FTP连接与数据浏览程序,实现实例化可操作的窗口。  部分源代码摘录:  ftpClient = new FtpClient(); //实例化FtpClient对象  String serverAddr=jtfServer.getText(); //得到服务器...

    java源码包3

     Java实现的FTP连接与数据浏览程序,实现实例化可操作的窗口。  部分源代码摘录:  ftpClient = new FtpClient(); //实例化FtpClient对象  String serverAddr=jtfServer.getText(); //得到服务器...

    JAVA上百实例源码以及开源项目

    百度云盘分享 ... Java实现的FTP连接与数据浏览程序,实现实例化可操作的窗口。  部分源代码摘录:  ftpClient = new FtpClient(); //实例化FtpClient对象  String serverAddr=jtfServer.getText();...

    JAVA上百实例源码以及开源项目源代码

     Java实现的FTP连接与数据浏览程序,实现实例化可操作的窗口。  部分源代码摘录:  ftpClient = new FtpClient(); //实例化FtpClient对象  String serverAddr=jtfServer.getText(); //得到服务器地址  ...

    java源码包2

     Java实现的FTP连接与数据浏览程序,实现实例化可操作的窗口。  部分源代码摘录:  ftpClient = new FtpClient(); //实例化FtpClient对象  String serverAddr=jtfServer.getText(); //得到服务器...

    Java开发技术大全(500个源代码).

    commSource.java 一个共享资源的类 demoSynchrony.java 演示线程的同步 setDataThread.java 设置数据的线程类 readDataThread.java 读取数据的线程类 demoEnhanceThread.java 使用自己定义的线程类示例 ...

    java核心面试技术点

    java 内存模型 ( java memory model ):根据Java Language Specification中的说明, jvm系统中存在一个主内存(Main Memory或Java Heap Memory),Java中所有对象成员变量都储存在主存中,对于所有线程都是共享的。...

    Java多线程编程经验

    现在的操作系统是多任务操作...线程总是属于某个进程,进程中的多个线程共享进程的内存。 “同时”执行是人的感觉,在线程之间实际上轮换执行。 本文档提供Java多线程编程经验,方便广大Java爱好者研究学习Java多线程

    java核心面试

    java 内存模型 ( java memory model ):根据Java Language Specification中的说明, jvm系统中存在一个主内存(Main Memory或Java Heap Memory),Java中所有对象成员变量都储存在主存中,对于所有线程都是共享的。...

    操作系统(内存管理)

    free:该函数获得指向由 malloc 分配的内存片段的指针,并将其释放,以便以后的程序或操作系统使用(实际上,一些 malloc 实现只能将内存归还给程序,而无法将内存归还给操作系统)。 物理内存和虚拟内存 要理解...

    成百上千个Java 源码DEMO 4(1-4是独立压缩包)

    Java实现的FTP连接与数据浏览程序 1个目标文件 摘要:Java源码,网络相关,FTP Java实现的FTP连接与数据浏览程序,实现实例化可操作的窗口。 部分源代码摘录: ftpClient = new FtpClient(); //实例化FtpClient对象 ...

    java多线程安全性基础介绍.pptx

    编译器和运行时不会讲该变量的操作与其他内存操作一起重排序 锁不仅保证原子性还保证可见性 有序性 多个线程操作共享对象导致的状态不一致问题 原因 共享资源的竞态条件问题 问题 竞态条件 指令重排序 ...

    Java并发:volatile内存可见性和指令重排

     工作内存中保存了主内存共享变量的副本,线程要操作这些共享变量,只能通过操作工作内存中的副本来实现,操作完毕之后再同步回到主内存当中。  如何保证多个线程操作主内存的数据完整性是一个难题

    Java多线程之进阶篇(一).docx

    与此相反,像java所使用的这种并发系统会共享内存或I/O这样的资源,因此编程编写多线程程序最基本的困难在于,协调不同线程驱动的任务之间这些资源的使用,以便使得这些资源不会同时被多个任务访问。

    Java多线程之基础篇(一).docx

    与此相反,像java所使用的这种并发系统会共享内存或I/O这样的资源,因此编程编写多线程程序最基本的困难在于,协调不同线程驱动的任务之间这些资源的使用,以便使得这些资源不会同时被多个任务访问。

    一篇文章弄懂Java多线程基础和Java内存模型

    通过Callable和Future接口创建线程三、Java内存模型概念四、内存间的交互操作五、volatile和synchronized的区别 写在前面:提起多线程大部门同学可能都会皱起眉头不知道多线程到底是什么、什么时候可以用到、用的...

    Java内存模型的历史变迁

     Java使用的是共享内存的并发模型,在线程之间共享变量。Java语言定义了线程模型规范,通过内存模型控制线程与变量的交互,从而实现Java线程之间的通信。在JDK5之前,Java一直使用的是旧内存模型。如图1所示。变量...

Global site tag (gtag.js) - Google Analytics