`

JAVA基础:共享内存在Java中的实现和应用

阅读更多

 

(转自 http://www.builder.com.cn/2008/0424/831162.shtml


    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应用中还是很有用的,只要组织好共享内存的数据结构,共享内存就可以在应用开发中发挥很不错的作用。


 

分享到:
评论

相关推荐

    共享内存在Java中的实现和应用.doc

    共享内存在Java中的实现和应用.doc

    Shamir:Shamir的秘密共享的Java实现

    GUI应用程序提供了使用Shamir的秘密共享的简单方法。 下载 本机软件包适用于MacOS和Windows,JAR适用于所有其他情况。 最新版本: 每个版本均经过PGP签名以确保安全性,并且可以在找到签名者的公钥。 从源头建造 您...

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

     Java 3DMenu 界面源码,有人说用到游戏中不错,其实平时我信编写Java应用程序时候也能用到吧,不一定非要局限于游戏吧,RES、SRC资源都有,都在压缩包内。 Java zip压缩包查看程序源码 1个目标文件 摘要:Java源码...

    全国计算机二级java题库

    掌握Java语言的特点,实现机制和体系结构。 2. 掌握Java语言中面向对象的特性。 3. 掌握Java语言提供的数据类型和结构。 4. 掌握Java语言编程的基本技术。 5. 会编写Java用户界面程序。 6. 会编写Java简单应用程序...

    java并发编程:线程基础

    本资源致力于向您介绍 Java 并发编程中的线程基础,涵盖了多线程编程的核心概念、线程的创建和管理,以及线程间通信的基本方法。通过深入学习,您将建立扎实的多线程编程基础,能够更好地理解和应用多线程编程。 多...

    java源码包2

     Java 3DMenu 界面源码,有人说用到游戏中不错,其实平时我信编写Java应用程序时候也能用到吧,不一定非要局限于游戏吧,RES、SRC资源都有,都在压缩包内。 Java zip压缩包查看程序源码 1个目标文件 摘要:Java...

    Java互联网人寿保险中台系统设计与实现

    适合人群:具备一定Java编程基础,工作1-4年的研发人员 能学到什么:①异步消息队列技术、共享缓存技术是怎么在系统中体现的;②互联网人寿保险中台系统都是如何设计和实现的。 阅读建议:此资源以开发互联网人寿...

    java实现数字签名

    电子政务是依赖于计算机和网络技术而存在的 而互联网具有的开放、平等、全球共享、交互、信息量巨大和传播快等特点,决定了电子政务应用不可避免地存在着由互联网 的自由、开放所带来的信息安全隐患。电子政务的所有...

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

     Java 3DMenu 界面源码,有人说用到游戏中不错,其实平时我信编写Java应用程序时候也能用到吧,不一定非要局限于游戏吧,RES、SRC资源都有,都在压缩包内。 Java zip压缩包查看程序源码 1个目标文件 摘要:Java源码...

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

     Java 3DMenu 界面源码,有人说用到游戏中不错,其实平时我信编写Java应用程序时候也能用到吧,不一定非要局限于游戏吧,RES、SRC资源都有,都在压缩包内。 Java zip压缩包查看程序源码 1个目标文件 摘要:Java源码...

    ScreenCatJavaScript实现的屏幕共享和远程协作应用

    JavaScript实现的屏幕共享和远程协作应用

    java源码包4

     Java 3DMenu 界面源码,有人说用到游戏中不错,其实平时我信编写Java应用程序时候也能用到吧,不一定非要局限于游戏吧,RES、SRC资源都有,都在压缩包内。 Java zip压缩包查看程序源码 1个目标文件 摘要:Java...

    JAVA文件传输的实现.rar

    在企业级应用中,可以作为分布式系统中的文件传输组件,实现不同节点之间的文件共享和同步。 通过Java文件传输的实现,可以实现快速、安全地在网络环境下进行文件传输,满足用户在不同场景下的文件管理和共享需求。

    java源码包3

     Java 3DMenu 界面源码,有人说用到游戏中不错,其实平时我信编写Java应用程序时候也能用到吧,不一定非要局限于游戏吧,RES、SRC资源都有,都在压缩包内。 Java zip压缩包查看程序源码 1个目标文件 摘要:Java...

    Java卡应用的设计与实现

    每个Applet实现一个部门的应用,处理特定的数据和 功能需求。在设计时,我们将持卡人的一些基本信息作为公共 属性分离出来,如持卡人的姓名、性别、出生日期、身份证号码 等,设计了一个公共Applet来存储这些基本...

    基于Java的共享学习资源系统的设计与实现【附源码】

    JSP是一种动态网页开发技术,主要用于实现应用程序的登录界面和资源信息等界面。JSP标签可以访问数据库、记录用户选择信息。 JSP可以直接在HTML网页中动态嵌入元素而不需要单独引用CGI文件。本系统将采用JSP技术,...

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

    HelloWorldApp.java 第一个用Java开发的应用程序。 firstApplet.java 第一个用Java开发的Applet小程序。 firstApplet.htm 用来装载Applet的网页文件 第2章 示例描述:本章介绍开发Java的基础语法知识。 ...

    java技术文档 常用类和经典应用

    Eclipse中Web应用开发基础.pdf HashSet类的用法.pdf Hashtable类的用法.pdf Java语言基础.pdf Math类的常用方法.pdf String与StringBuffer.pdf Vector类的用法.pdf 迭代器Iterator的用法.pdf 反射机制.pdf 访问路经...

    Java 语言基础 —— 非常符合中国人习惯的Java基础教程手册

    用程序之中,通过这些对象的相互作用,程序员可实现高层次的操作和更负责的功能。某此 对象通过向其他对象发送消息与其他对象进行交互作用和通信。 消息是以参数的形式传递给某方法的。一个消息通常由三部分组成: 1...

    西南科技大学Java程序设计与实践 实验三 类的继承与多态的应用

    西南科技大学Java程序设计与实践 实验三 类的继承与多态的应用 一、实验目的: 1、练习类的继承与多态设计过程; 2、练习面向对象的图形用户界面设计、事件设计方法。 二、实验内容: 1、利用多态性编程,创建一个 ...

Global site tag (gtag.js) - Google Analytics