专注于互联网--专注于架构

最新标签
网站地图
文章索引
Rss订阅

首页 »Java教程 » 共享内存在Java中的实现和应用 »正文

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

来源: 发布时间:星期一, 2009年4月6日 浏览:0次 评论:0
1 共享内存对应应用开发意义JAVA中文站社区门户$Ft2dSB2]2}5H#T
对熟知UNIX系统应用开发员来说IPC(InterProcess Communication)机制是非常熟悉IPC基本包括共享内存、信号灯操作、消息队列、信号处理等部分是开发应用中非常重要必不可少工具其中共享内存IPC机制关键对于数据共享、系统快速查询、动态配置、减少资源耗费等均有独到优点JAVA中文站社区门户d#k:`/X8x%nk-i
JAVA中文站社区门户"d*v9|1p:rZ
对应UNIX系统来说共享内存分为般共享内存和映像文件共享内存两种而对应 Windows实际上只有映像文件共享内存所以java应用中也是只能创建映像文件共享内存JAVA中文站社区门户BLEY ~*Ln
JAVA中文站社区门户E0H7R9yP w m
在java语言中基本上没有提及共享内存这个概念但是在某些应用中共享内存确实非常有用例如采用java语言分布式应用系统中存在着大量分布式共享对象很多时候需要查询这些对象状态以查看系统是否运行正常或者了解这些对象目前些统计数据和状态如果采用网络通信方式显然会增加应用额外负担也增加了些不必要应用编程而如果采用共享内存方式则可以直接通过共享内存查看对象状态数据和统计数据从而减少了些不必要麻烦
V ijlfY8wf1~9J
_'X!DA~lQ*V&?$l`共享内存使用有如下几个特点:
(]+Hb$aMT"c%V w[7uJAVA中文站社区门户{ oD5n2mor
可以被多个进程打开访问;
,z9r#n j2YbU读写操作进程在执行读写操作时其他进程不能进行写操作; JAVA中文站社区门户^(] uGc]0Q
多个进程可以交替对某共享内存执行写操作; JAVA中文站社区门户kdy%]S0@K(V`!v2J(S
个进程执行了内存写操作后不影响其他进程对该内存访问同时其他进程对更新后内存具有可见性
'v9l| R2Bg在进程执行写操作时如果异常退出对其他进程写操作禁止应自动解除 JAVA中文站社区门户v5m1jk~
相对共享文件数据访问方便性和效率有
zC6] ?+BVd(w3NH3w
gT%N\li9T mP }JAVA中文站社区门户:UVp(vDto

\ F C]:P'p)n2v另外共享内存使用上有如下情况:
^aB"qt$z$]
Fy-] aGBR`n)l独占写操作相应有独占写操作等待队列独占写操作本身不会发生数据致性问题 JAVA中文站社区门户A,A a dq@o:`:e4f|
共享写操作相应有共享写操作等待队列共享写操作则要注意防止发生数据致性问题 JAVA中文站社区门户4i,cU%ns"O
独占读操作相应有共享读操作等待队列; JAVA中文站社区门户:`*V,h9u&g(W+_
共享读操作相应有共享读操作等待队列 JAVA中文站社区门户[3__3@ [8[
JAVA中文站社区门户 { g&m_3q/G_

6r Zd'^+z"t1O9g
R4Kpf8{_*bP般情况下我们只是关心第 2种情况JAVA中文站社区门户lL0_7PVj

C&P+j@2{5p\ c2 共享内存在java中实现
8A4o in9b:@ R'm*TSqk在jdk1.4中提供类MappedByteBuffer为我们实现共享内存提供了较好思路方法该缓冲区实际上是个磁盘文件内存映像 2者变化将保持同步即内存数据发生变化会立刻反映到磁盘文件中这样会有效保证共享内存实现
aU4q0u+yv
&GH!SKl.t)^Ig将共享内存和磁盘文件建立联系是文件通道类:FileChannel该类加入是JDK为了统对外部设备(文件、网络接口等)访问思路方法并且加强了多线程对同文件进行存取安全性例如读写操作统成read和write这里只是用它来建立共享内存用它建立了共享内存和磁盘文件的间个通道
\anIj V0fa?.s
f`0d _ _R9|-h(XZf打开个文件建立个文件通道可以用RandomAccessFile类中思路方法getChannel该思路方法将直接返回个文件通道该文件通道由于对应文件设为随机存取文件方面可以进行读写两种操作方面使用它不会破坏映像文件内容(如果用FileOutputStream直接打开个映像文件会将该文件大小置为0当然数据会全部丢失)这里如果用 FileOutputStream和FileInputStream则不能理想实现共享内存要求这两个类同时实现自由读写操作要困难得多JAVA中文站社区门户(TN`_8i0R+au

/Z?$i#y.D~'_d下面代码实现了如上功能作用类似UNIX系统中mmapJAVA中文站社区门户0lC Ig,\6f
JAVA中文站社区门户u*g,VzQ)gT
// 获得个只读随机存取文件对象
4s-bT/~&j3K wRandomAccessFile RAFile = RandomAccessFile(filename,"r");
x.ox1a{0fh D5} o
;J+{W$I/{3gE j// 获得相应文件通道JAVA中文站社区门户 S1q9|sd~O
FileChannel fc = RAFile.getChannel;JAVA中文站社区门户.d Ij(d7s Z

U t7j8d {0i u IH `// 取得文件实际大小以便映像到共享内存
nKj,_r size = ()fc.size;
^^G'i&^-VJAVA中文站社区门户nW;e/@.x,y
// 获得共享内存缓冲区该共享内存只读
:m0y&] ~7`DxZ~MappedByteBuffer mapBuf = fc.map(FileChannel.MAP_RO,0,size);
8f%IAN:G$[%Oj iT
-ArF{~T// 获得个可读写随机存取文件对象JAVA中文站社区门户 Y jtReY-gD*d!x^
RAFile = RandomAccessFile(filename,"rw");JAVA中文站社区门户LDvP9tFT

fhvPP5h,@r8T// 获得相应文件通道
#k%T3m/f'r]fc = RAFile.getChannel;JAVA中文站社区门户!K q`)\3J6Es}
JAVA中文站社区门户C/gXB6q,_!|u
// 取得文件实际大小以便映像到共享内存
AVQ |1~Psize = ()fc.size;JAVA中文站社区门户Z@])l@

7x,W DIt(gF// 获得共享内存缓冲区该共享内存可读写JAVA中文站社区门户0\8ym!s2q/Y~(V
mapBuf = fc.map(FileChannel.MAP_RW,0,size);JAVA中文站社区门户V}!D"Mt^6W

_dpp5c l// 获取头部消息:存取权限
|m|'C%NuY0]#Gmode = mapBuf.getInt;
N%R!{ j8~9]+u;e Z}0wJAVA中文站社区门户1o3U1p6n js1RrR
如果多个应用映像同文件名共享内存则意味着这多个应用共享了同内存数据这些应用对于文件可以具有同等存取权限个应用对数据刷新会更新到多个应用中JAVA中文站社区门户c7^b1\1f[
JAVA中文站社区门户9Igql%o
为了防止多个应用同时对共享内存进行写操作可以在该共享内存头部信息加入写操作标志该共享内存头部基本信息至少有:
*mP7Na-KCkJAVA中文站社区门户0r@ sO4K&\
Length; // 共享内存长度
,[3Q |3Du mode; // 该共享内存目前存取模式
0h v8i9k)C.e/VJAVA中文站社区门户qP0A,a9g?

Z1g$|/d A+_JAVA中文站社区门户{b[c P R

1I`2X|@JAVA中文站社区门户 W*Li;e |\5F;Vp

7EQfv\O JX3f(G7T共享内存头部信息是类私有信息在多个应用可以对同共享内存执行写操作时开始执行写操作和结束写操作时如下思路方法:JAVA中文站社区门户7U oc`.k%I.@a
JAVA中文站社区门户 p6th j-wci,V$] tO
public boolean StartWriteJAVA中文站社区门户,kF:N2~]
{
~+Z)@5]`(i d[C(mode 0) { // 标志为0则表示可写
S7PEzd9QtLmode = 1; // 置标志为1意味着别应用不可写该共享内存
m\}2GHQ*hAjS&x-B\mapBuf.flip; JAVA中文站社区门户2b|WG*ng
mapBuf.putInt(mode); // 写如共享内存头部信息JAVA中文站社区门户it7z_7vS,zV
true;JAVA中文站社区门户:{}"n [Qj]
}JAVA中文站社区门户hvH:Zl;F qGc V4v
{JAVA中文站社区门户S0L'^_ h!{Vx L
false; // 指明已经有应用在写该共享内存本应用不可写该共享内存
4|A4bQt D"Z^ Q}
I8R)q$a(?]a,X}
KA+Z7J e
^/yq} J BLpublic boolean StopWriteJAVA中文站社区门户 G _7VK1Q,D
{
X#yc!_.y"|1D"imode = 0; // 释放写权限JAVA中文站社区门户s ^v,D fG)i.aL?b
mapBuf.flip; JAVA中文站社区门户 g faQYXx$|(o#}
mapBuf.putInt(mode); // 写入共享内存头部信息
hK(|A nR E true;
E5o*y4]b;N)r}
.a&Lb4{M\
'L|:n*]5}mJAVA中文站社区门户@ t g7Jm7x \
这里提供类文件mmap.java封装了共享内存基本接口读者可以用该类扩展成自己需要功能全面JAVA中文站社区门户-`In Kt

jp0~*Ri,d.jfyyJAVA中文站社区门户/i jo4}J"W/S8T!A4{,[C
如果执行写操作应用异常中止那么映像文件共享内存将不再能执行写操作为了在应用异常中止后写操作禁止标志自动消除必须让运行应用获知退出应用在多线程应用中可以用同步思路方法获得这样效果但是在多进程中同步是不起作用思路方法可以采用多种窍门技巧这里只是描述可能实现:采用文件锁方式写共享内存应用在获得对个共享内存写权限时候除了判断头部信息写权限标志外还要判断个临时锁文件是否可以得到如果可以得到则即使头部信息写权限标志为1(上述)也可以启动写权限其实这已经表明写权限获得应用已经异常退出这段代码如下:JAVA中文站社区门户!F [3LE'g Ua-E
JAVA中文站社区门户l@7?3Z5Sb$m:z(@
// 打开个临时文件注意同共享内存该文件名要相同可以在共享文件名后加后缀“.lock”JAVA中文站社区门户rD_9a+`Y*R#Fo
RandomAccessFile fis = RandomAccessFile("shm.lock","rw");JAVA中文站社区门户kt sTG(p&`p.X
// 获得文件通道
.U lhSOM8FHo&H^FileChannel lockfc = fis.getChannel;JAVA中文站社区门户w$Q.jV5X:zB
// 获得文件独占锁该思路方法不产生堵塞立刻返回
\1}f#ZABxiFileLock flock = lockfc.tryLock;JAVA中文站社区门户e-}wi5?y-c B U0f
// 如果为空则表明已经有应用占有该锁JAVA中文站社区门户2Qm {dK|4UMW#O[,m
(flock null) {
F;Kq2h;Ec~rT...// 不能执行写操作
'Iq_s-v(OdtA}JAVA中文站社区门户:@m ^2\kB
{
,zG&N~ |Ne']8e...// 可以执行写操作JAVA中文站社区门户$b,HA y;p D9q+d
}JAVA中文站社区门户$J3EV0Xm p
JAVA中文站社区门户`6o Z@ck#C
JAVA中文站社区门户/n;[+e"l w
JAVA中文站社区门户I{2q D z5Lie
该锁会在应用异常退出后自动释放这正是该处所需要思路方法
9q EwN~B0E+R~9UDJAVA中文站社区门户qMS7I8{&z!Y6_
JAVA中文站社区门户4i#kn1r;E\L D I
3 共享内存在java中应用JAVA中文站社区门户c7}Y,Q `*W(bp
共享内存在java应用中经常有如下两种种应用:JAVA中文站社区门户]m(S.Hs
JAVA中文站社区门户 I$Fu#a,rZ
永久对象配置 JAVA中文站社区门户XV(l\4U8g9a
在java服务器应用中用户可能会在运行过程中配置些参数而这些参数需要永久有效当服务器应用重新启动后这些配置参数仍然可以对应用起作用这就可以用到该文中共享内存该共享内存中保存了服务器运行参数和些对象运行特性可以在应用启动时读入以启用以前配置参数JAVA中文站社区门户 k#E D8^:?4W0w%Cu d
JAVA中文站社区门户9BX{-K5]3Tz
查询共享数据
+o6kEn'H+i个应用(例 sys.java)是系统服务进程其系统运行状态记录在共享内存中其中运行状态可能是不断变化为了随时了解系统运行状态启动另个应用(例 mon.java)该应用查询该共享内存汇报系统运行状态JAVA中文站社区门户7I9PK V:|
JAVA中文站社区门户Lk B7tVesP@!F
可见共享内存在java应用中还是很有用只要组织好共享内存数据结构共享内存就可以在应用开发中发挥很不错作用JAVA中文站社区门户G ~3G@.V
JAVA中文站社区门户o(E*](r;c8q,~4VOh
有关作者 JAVA中文站社区门户t#hLs6]WU
郭洪锋从事UNIX系统上分布式应用系统开发已有 4年分布式应用系统开发经验E-mail:[email protected]

TAG: Java JAVA java 应用
标签:
0

相关文章

读者评论

发表评论

  • 昵称:
  • 内容: