java 共享内存-tomcat集群内存共享
基于Java平台共享内存的实现与应用(张华杰郑州广播电视大学河南郑州450007【摘要】:在java开发环境中,没有涉及共享内存这个概念,但是在某一些应用中,“共享内存”确实非常有用。在java语言的分布式应用系统中,存在着大量的分布式共享对象,很多时候需要查询这些对象的状态,如果采用网络通信的方式,会增加应用的额外负担;如果采用共享内存的方式,则可以直接通过共享内存查看对象的状态数据和统计数据,减少了一些不必要的麻烦。【关键字】:共享内存、java共享内存对应用开发的意义:IPC(InterProcessCommunication)基本包括共享内存、信号灯操作、消息队列、信号处理等部分,是开发应用中非常重要的必不可少的工具。其中共享内存IPC机制的关键,对于数据共享、系统快速查询、动态配置、减少资源耗费等均有独到的优点。对应UNIX系统来说,共享内存分为一般共享内存和映像文件共享内存两种,而对应Windows,实际上只有映像文件共享内存一种。所以java应用中也是只能创建映像文件共享内存。共享内存在java中的实现在jdk中提供的类MappedByteBuffer为我们实现共享内存提供了较好的方法。
该缓冲区实际上是一个磁盘文件的内存映像。二者的变化将保持同步,即内存数据发生变化会立刻反映到磁盘文件中,这样会有效的保证共享内存的实现。将共享内存和磁盘文件建立联系的是文件通道类:FileChannel。该类的加入是JDK了统一对外部设备的访问方法,并且加强了多线程对同一文件进行存取的安全性。例如读写操作统一成read和write。这里只是用它来建立共享内存用,它建立了共享内存和磁盘文件之间的一个通道。开一个文件建立一个文件通道可以用RandomAccessFile类中的方法getChannel。该方法将直接返回一个文件通道。该文件通道由于对应的文件设为随机存取文件,一方面可以进行读写两种操作,另一方面使用它不会破坏映像文件的内容。这里如果用FileOutputStreamFileInputStream则不能理想的实现共享内存的要求,因为这两个类同时实现自由的读写操作要困难得多。一下过程实现了如这种功能;RandomAccessFileRAFilenewRandomAccessFile(filename,"r");//获得一个只读的随机存取文件对象FileChannelfcRAFile.getChannel();//获得相应的文件通道intsize(int)fc.size();//取得文件的实际大小,以便映像到共享内存MappedByteBuffermapBuf获得共享内存缓冲区,该共享内存只读RAFilenewRandomAccessFile(filename,"rw");//获得一个可读写的随机存取文件对象fcRAFile.getChannel();//获得相应的文件通道size(int)fc.size();//取得文件的实际大小,以便映像到共享内存mapBufmapBuf.getInt();//获取头部消息:存取权限如果多个应用映像同一文件名的共享内存,则这多个应用共享了同一内存数据。
这些应用对于文件可以具有同等存取权限,一个应用对数据的刷新会更新到多个应用中。为了防止多个应用同时对共享内存进行写操作,可以在该共享内存的头部信息加入写操作标志。该共享内存的头部基本信息至少有:intLength;共享内存的长度。intmode;该共享内存目前的存取模式。共享内存的头部信息是类的私有信息,在多个应用可以对同一共享内存执行写操作时,开始执行写操作和结束写操作时,需调用如下方法:publicbooleanStartWrite(){if(mode标志为0,则表示可写mode置标志为1,意味着别的应用不可写该共享内存mapBuf.flip();mapBuf.putInt(mode);写如共享内存的头部信息returntrue;}elsereturnfalse;指明已经有应用在写该共享内存,本应用不可写该共享内存}}publicbooleanStopWrite(){mode释放写权限mapBuf.flip();mapBuf.putInt(mode);写入共享内存头部信息returntrue;}这里提供的类文件mmap.java封装了共享内存的基本接口java 共享内存,读者可以用该类扩展成自己需要的功能全面的类。
如果执行写操作的应用异常中止,那么映像文件的共享内存将不再能执行写操作。为了在应用异常中止后,写操作禁止标志自动消除,必须让运行的应用获知退程应用中,可以用同步方法获得这样的效果,但是在多进程中,同步是不起作用的。方法可以采用的多种技巧,这里只是描述一可能的实现:采用文件锁的方式。写共享内存应用在获得对一个共享内存写权限的时候,除了判断头部信息的写权限标志外java 共享内存,还要判断一个临时的锁文件是否可以得到,如果可以得到,则即使头部信息的写权限标志为打开一个临时的文件,注意同一共享内存,该文件名要相同,可以在共享文件名后加后缀“.lock”。RandomAccessFilefisnewRandomAccessFile("shm.lock","rw");获得文件通道FileChannellockfc获得文件的独占锁,该方法不产生堵塞,立刻返回FileLockflock如果为空,则表明已经有应用占有该锁if(flock不能执行写操作}else可以执行写操作}该锁会在应用异常退出后自动释放,这正是该处所需要的方法。三、共享内存在java中的应用共享内存在java应用中,经常有如下两种种应用:永久对象配置。
在java服务器应用中,用户可能会在运行过程中配置一些参数,而这些参数需要永久有效,当服务器应用重新启动后,这些配置参数仍然可以对应用起作用。这就可以用到该文中的共享内存。该共享内存中保存了服务器的运行参数和一些对象运行特性。可以在应用启动时读入以启用以前配置的参数。查询共享数据。一个应用(例sys.java)是系统的服务进程,其系统的运行状态记录在共享内存中,其运行状态可能是不断变化的。为了随时了解系统的运行状态,启动另一个应用(例mon.java),该应用查询该共享内存,汇报系统的运行状态。可见,共享内存在java应用中还是很有用的,只要组织好共享内存的数据结构,共享内存就可以在应用开发中发挥很不错的作用。四、【参考文献】《Linux程序设计》人民邮电出版社2007[2]、埃克尔(Eckel.B):《ThinkingJava》机械工业出版社1999《JAVA面向对象编程》电子工业出版社2006.7等编著:《计算机操作系统》西安电子科技大学出版社2007.5