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实现局域网桌面共享涉及到网络编程、多线程、图像处理、数据传输协议等多个领域,而项目中提及的线程优化问题需要进一步关注和改进。通过不断优化和调试,这个应用可以变得更加健壮和高效。
在Java编程环境中,有时我们需要与Windows操作系统进行交互,例如访问共享目录并下载其中的文件。这个过程涉及到几个关键的技术点,包括...在实际应用中,这样的功能可以用于自动化任务、文件同步或数据备份等场景。
本文详细介绍了如何使用Java语言结合jcifs库操作Windows共享目录的方法,主要包括了SMB协议的基本概念及其在Windows系统中的应用,以及jcifs库的功能特点和具体使用示例。通过对这些内容的学习,开发者可以更好地...
在Java编程环境中,处理共享文件是一项常见的任务,特别是在企业级应用中,可能需要访问网络上的文件系统资源。Java提供了一些库来实现这一功能,其中之一就是jcifs库,它是一个开源的Java SMB(Server Message ...
Java 局域网文件共享程序是一种利用Java编程语言开发的应用,旨在实现局域网内的文件共享、下载以及聊天功能。这种程序通常通过网络编程技术,如Socket编程和多线程处理,来实现在同一网络环境下的设备间进行高效的...
在实际应用中,频繁地创建和销毁线程会消耗大量系统资源。Java 5及以上版本引入了ExecutorService和ThreadPoolExecutor,它们可以帮助我们管理线程池,有效地复用线程,减少系统开销。在小球运动模拟中,可能使用...
在信息技术领域中,Java卡技术作为一种智能卡的解决方案,其对象共享机制是实现多应用共存的关键技术。然而,这种机制同样伴随着安全风险。本文旨在分析Java卡对象共享机制的安全问题,并提出了相应的解决策略。 ...
在这个Java实现中,我们利用了MAVEN作为项目管理工具和OLTU库来构建OAuth 2.0服务端和客户端。同时,数据加密采用了MD5算法,以增强安全性。 首先,OAuth 2.0的核心概念包括四个角色:资源所有者(Resource Owner)...
尽管Java语言在软件开发中具有广泛的应用和优势,但它在实际应用中也存在一些问题。主要问题体现在C语言异常处理、参数处理和数据处理等方面。异常处理通常涉及到软件的健壮性,合理地使用异常处理能够确保软件的...
多线程技术是Java高级程序语言解决并发处理问题的核心方案,在网络通信系统设计...在实际应用中,开发者需要深入理解多线程编程的挑战,合理运用Java提供的同步控制机制和网络通信机制,以确保网络通信系统的稳定运行。
在这个聊天室应用中,采用了经典的客户端/服务器架构。服务器端负责处理用户的登录认证、消息转发等功能,而客户端则负责发送消息和接收服务器响应。 1. **服务器端**:服务器监听来自客户端的连接请求,并为每个新...
在Java中实现Oracle变量的绑定方法,主要是为了优化SQL语句的执行效率,减少数据库解析负担,提升系统性能。Oracle数据库在处理SQL语句时,会先进行解析,然后将解析后的SQL语句存储在共享池(Shared Pool)中。如果...
以上就是Java中实现单例模式的常见方法,每种方式都有其适用场景和优缺点。在实际开发中,我们需要根据项目需求选择合适的方式实现单例。同时,理解单例模式背后的原理和应用场景,有助于提升代码的设计质量。
【纯Java音乐共享平台】是一个由个人开发的项目,它完全基于Java编程语言,利用Swing库构建用户界面,同时结合多线程和Socket网络通信技术来实现音乐资源的共享功能。这个平台允许用户在客户端与服务器之间进行交互...
在IT行业中,尤其是在分布式系统和网络编程领域,"Java共享文件夹接口"是一个重要的概念,它允许客户端应用程序访问和操作远程服务器上的文件,尤其是Word文档。这个接口的设计目的是为了实现跨平台的数据共享和协作...
《基于Java的物品交换平台设计与实现》 在信息技术飞速发展的今天,物品交换平台已经成为了互联网服务中不可或缺的一部分。...尽管细节可能存在不足,但整体功能的完备性使得该平台具备了实际应用的潜力。
综上所述,这个“java实现的多线程服务器”项目涵盖了Java多线程编程、网络编程、并发控制、异常处理和性能优化等多个重要知识点,对于学习和实践Java服务器开发具有很高的价值。通过深入研究和理解这个项目,开发者...
它提供了一种基于分布式数据一致性模型的树状数据结构,使得多个应用程序可以共享和维护同一份分布式数据。 **ZooKeeper应用领域** ZooKeeper在分布式系统中扮演着重要角色,主要应用于以下几个方面: 1. **配置...