大部分情况下,我们面对在两个java进程只见传递数据的问题时,第一个想到的就是开server,然后通过socket收发消息。这方面有大量的框架可用,就不细说了。
但如果两个进程是在一台机器上,那么还可以使用另一种方式来传递数据,那就是使用RandomAccessFile的文件映射模式。
RandomAccessFile的map方法把文件映射到内存中进行快速读写。因此可以通过把消息包写入到文件中,然后另一个进程读取出来的方式来完成数据传递。
在这个过程中,重点是要考虑什么时候写入完成,只有写入完成后,读取进程才可以去读数据,否则就是错误的数据。具体方案如下:
保留文件的首个byte作为标志位,1表示A进程写入完毕,0表示B进程读取完毕。
步骤1:A进程开始写入时,先跳过首字节,然后将数据长度,数据内容写入到文件。写入完毕后,将文件的首字节置为1
步骤2:B进程定时刷新文件到内存中,读取首字节,如果是0则跳出,等待下次刷新。如果是1表示有新数据,则加载。加载完毕后设置首字节为0.表示已经读取完毕。
步骤3:A进程定时刷新文件到内存,读取首字节,如果是0,表示可以写入,继续步骤1的流程。如果是1,则表示数据还没被读取,不可写入。等待下次刷新。
经过以上3个步骤,完成数据的进程间传递。此模式也可以用于将数据传递到非java进程。
代码如下:

public class TestRandomAccessFile {
private static String FileName="aa.a";
private static volatile Linux1 lx1;
private static volatile Linux2 lx2;
private static long from; private static void close(Closeable c){
try{
c.close();
}catch(IOException ie){
ie.printStackTrace();
}
} public static class Linux1{
MappedByteBuffer buf;
RandomAccessFile raf; public Linux1(){
try{
raf = new RandomAccessFile(FileName, "rw");
buf = raf.getChannel().map(MapMode.READ_WRITE, 0, 1024*1024);
}catch(IOException ie){
ie.printStackTrace();
}
new Thread(()->{
try{
while(true){
readAndWrite();
}
}catch(IOException e){
e.printStackTrace();
}
}).start(); } private void readAndWrite() throws IOException {
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
String s = reader.readLine();
if(s != null){
if("exit".equalsIgnoreCase(s)){
exitAll();
}else{
write(s);
}
}
} private void write(String s){
if(s.length() == 0)return;
buf.load();
buf.position(0);
byte mark = buf.get();
while(mark != 0){
buf.load();
mark = buf.get();
}
if(s != null && s.length() > 0){
buf.putShort((short)s.length());
for (int i = 0; i< s.length(); i++){
buf.putChar(s.charAt(i));
}
buf.position(0);
buf.put((byte)1); //加可读标记
buf.force();
from = System.nanoTime();
}
} public void exit(){
close(raf);
}
} public static class Linux2{
MappedByteBuffer buf;
RandomAccessFile raf;
public Linux2(){
try{
raf = new RandomAccessFile(FileName, "rw");
buf = raf.getChannel().map(MapMode.READ_WRITE, 0, 1024*1024);
}catch(IOException e){
e.printStackTrace();
} new Thread(()->{
while(true){
checkAndRead();
if(from > 0){
long t = (System.nanoTime()-from);
System.out.println("time=" + t);
from = -1;
}
try{
TimeUnit.NANOSECONDS.sleep(1);
}catch(Exception e){
e.printStackTrace();
}
}
}).start();
} private void checkAndRead(){
buf.load();
if(buf.remaining() == 0)return;
buf.position(0);
byte mark = buf.get();
if(mark == 0)return;
int len = buf.getShort();
if(len > 0){
char[] cs = new char[len];
for (int i = 0; i< len; i++){
cs[i] = buf.getChar();
}
// /System.out.println("***** " + new String(cs));
}
buf.position(0);
buf.put((byte)0);
} public void exit(){
close(raf);
}
} public static void exitAll(){
lx1.exit();
lx2.exit();
System.exit(0);
} public static void main(String[] args){
lx1 = new Linux1();
lx2 = new Linux2();
}
}

测试下来,使用netty走socket传数据,时间在0.5-1ms之间。用RandomAccessFile模式传数据,则依赖于轮询快慢。由于java定时器的误差,及时是用Thread.sleep(0,1)的方式,我们也只能做到平均1ms左右的延迟。但如果是不sleep(现实不能如此,会导致单核被完全占用),那么延迟可以在0.001ms。所以如果能找到一种更有效的轮询方法,那么使用RandomAccessFile进行进程间数据传输的效率会更高,如果不能,那还不如就Socket模式吧,更通用。

使用RandomAccessFile在两个java进程之间传递数据的更多相关文章

  1. 用WM_COPYDATA消息来实现两个进程之间传递数据

    文着重讲述了如果用WM_COPYDATA消息来实现两个进程之间传递数据. 进程之间通讯的几种方法:在Windows程序中,各个进程之间常常需要交换数据,进行数据通讯.常用的方法有   1.使用内存映射 ...

  2. python进程之间修改数据[Manager]与进程池[Pool]

    #前面的队列Queue和管道Pipe都是仅仅能再进程之间传递数据,但是不能修改数据,今天我们学习的东西就可以在进程之间同时修改一份数据 #Mnager就可以实现 import multiprocess ...

  3. 两个java工程之间的相互调用方法

    如果你有两个java项目的话,如何向他们之间进行信息的通信前提:必须知道要通信的java项目(接收请求方)的服务器的IP地址和访问路径.其实两个java项目之间的通信还是使用HTTP的请求.主要有两种 ...

  4. Python 进程之间共享数据

    最近遇到多进程共享数据的问题,到网上查了有几篇博客写的蛮好的,记录下来方便以后查看. 一.Python multiprocessing 跨进程对象共享  在mp库当中,跨进程对象共享有三种方式,第一种 ...

  5. Python 进程之间共享数据(全局变量)

    进程之间共享数据(数值型): import multiprocessing def func(num): num.value=10.78 #子进程改变数值的值,主进程跟着改变 if __name__= ...

  6. Activity之间传递数据的方式及常见问题总结

    Activity之间传递数据一般通过以下几种方式实现: 1. 通过intent传递数据 2. 通过Application 3. 使用单例 4. 静态成员变量.(可以考虑 WeakReferences) ...

  7. Android 笔记-Fragment 与 Activity之间传递数据

    Fragment 与 Activity之间传递数据有两种方法.一种是使用setArgument,一种是使用接口回调.以下先学习第一种方法. (1)使用setArgument方法: 为了便于理解,我在这 ...

  8. Activity之间传递数据或数据包Bundle,传递对象,对象序列化,对象实现Parcelable接口

    package com.gaojinhua.android.activitymsg; import android.content.Intent; import android.os.Bundle; ...

  9. 【Android 复习】 : Activity之间传递数据的几种方式

    在Android开发中,我们通常需要在不同的Activity之间传递数据,下面我们就来总结一下在Activity之间数据传递的几种方式. 1. 使用Intent来传递数据 Intent表示意图,很多时 ...

随机推荐

  1. C++—this指针的用法

    this指针抽象比喻 当我们在进入一个房子之后, 可以看见房子里的桌子,椅子. 地板等,但是看不到房子的全貌.对于一个类的实例来说, 你可以看到它的成员 函数. 成员 变量, 但是实例本身呢? thi ...

  2. Linux运行级别简介

    init 0 : 关机 init 1 : 单用户模式  root init 2 : 多用户模式 不能使用 net file system init 3 : 完全多用户模式 init 4 : 多用户的安 ...

  3. 【SF】开源的.NET CORE 基础管理系统 - 安装篇

    [SF]开源的.NET CORE 基础管理系统 -系列导航 1.开发必备工具 IDE:VS2017 运行环境:netcoreapp1.1 数据库:SQL Server 2012+ 2.获取最新源代码 ...

  4. iOS开发之数据存储之Preference(偏好设置)

    1.概述 很多iOS应用都支持偏好设置,比如保存用户名.密码.字体大小等设置,iOS提供了一套标准的解决方案来为应用加入偏好设置功能. 每个应用都有个NSUserDefaults实例,通过它来存取偏好 ...

  5. linux 安装sysstat使用iostat、mpstat、sar、sa

    使用yum安装 #yum install sysstat sysstat的安装包是:sysstat-5.0.5-1.i386.rpm,装完了sysstat-5.0.5-1.i386.rpm后 就会有i ...

  6. deepin系统下如何设置wifi热点(亲测有效)

    deepin系统下如何设置wifi热点(亲测有效) deepin wifi ap linux 热点 首先必须吐槽一下linux下设置wifi太累了....来来回回折腾了我好久的说.心累... 好了废话 ...

  7. 浅谈对java中传参问题的理解

    之前用的c/c++比较多,在c/c++中对于传参类型,无外乎就是传值.传引用.传指针这几种.但在java中,由于没有指针类型,其传参的方式也发生了相应的变化.在网上找了找,按我之前的理解,java中传 ...

  8. 【Java 并发】详解 ThreadLocal

    前言 ThreadLocal 主要用来提供线程局部变量,也就是变量只对当前线程可见,本文主要记录一下对于 ThreadLocal 的理解.更多关于 Java 多线程的文章可以转到 这里. 线程局部变量 ...

  9. CDN内容分发网络

    CDN的全称是Content Delivery Network,即内容分发网络,其设计思想是尽可能避开互联网上有可能影响数据传输速度和稳定性的瓶颈和环节,使内容传输的更快.更稳定. CDN系统是在网络 ...

  10. suse安装svn服务端和客户端的使用

    suse安装svn服务端 一. 安装服务端 配置网络安装源(suse11sp1为例) 新建11.1.repo11.1为软件源名称,可自定义文件并添加如下内容后保存 linux-e0xg:/etc/zy ...