java进程间通讯机制代码

来源:互联网 发布:淘宝一年营业额 编辑:程序博客网 时间:2024/06/06 05:15

java进程间通讯机制代码

socket
RMI远程调用
共享内存
管道

进程间利用socket来通信

客户端每隔500毫秒向服务器发送一个奇数,服务器将已收到的奇数乘以2再发回给客户。


客户端程序

import java.io.*;import java.net.*;public class client {  public static void main(String[] args) {    String s = null;    Socket mysocket;    DataInputStream in = null;     DataOutputStream out = null;    try{    mysocket = new Socket("127.0.0.1", 4331); in = new DataInputStream(mysocket.getInputStream()); ///*mysocket可以使用getInputStream()方法获得一个输入流,然后用这个输入流读取服务器放入“线路”的信息,还可以使用getOutputStream()方法获得一个输出流,然后用这个输出流将信息写入“线路”*/out = new DataOutputStream(mysocket.getOutputStream());    for(int k=1; k<10; k=k+2) {    out.writeUTF("" + k);    s=in.readUTF();    System.out.println("客户收到:" + s);    Thread.sleep(500);    }  }  catch(Exception e) {         System.out.println("服务器已断开" + e);      } }}

服务器端程序

import java.io.*;  import java.net.*;  public class server {  public static void main(String[] args) {  ServerSocket server = null;  Socket you = null;  String s = null;  DataOutputStream out = null;  DataInputStream in = null;  try{                    server = new ServerSocket(4331);       }catch(IOException e) {  System.out.println(e);}//有备注    try{System.out.println("等待客户呼叫");  you = server.accept();  out = new DataOutputStream(you.getOutputStream());  in = new DataInputStream(you.getInputStream());  while(true) {s = in.readUTF();  int m=Integer.parseInt(s);  out.writeUTF("你好:我是服务器");  out.writeUTF("你说的数" + m + "乘2后是:" + 2*m);System.out.println("服务器收到:" + s);  Thread.sleep(500);}} catch(Exception e) {System.out.println("客户以断开" + e);}}  }//有备注  


先运行服务器端程序,再运行客户端程序



RMI远程方法调用

RMI(Remote MethodInvocation)是一种基于Java的分布式编程模型,为java程序提供远程访问服务接口。它允许允许在一个java虚拟机上的对象调用允许在另一台java虚拟机上的对象的方法,就像调用本地方法一样。

//创建远程接口及声明远程方法(HelloInterface.java)import java.rmi.*;   public interface HelloInterface extends Remote {public String  say() throws RemoteException; }/* 远程接口必须扩展java.rmi.remote*//*远程接口方法必须抛出* java.rmi.RemoteException*/

//实现远程接口及远程方法(继承UnicastRemoteObject)(Hello.java)import java.rmi.*;import java.rmi,server.*;public class Hello extends UnicastRemoteObject implements HelloInterface {private String message;    public Hello(String msg) throws RemoteException {Message = msg;}  /** 远程接口方法的实现  */public String say() throws RemoteException {System.out.println("CalledbyHelloClient");return message;}  //备注}

//启动RMI注册服务,并注册远程对象(HelloServer.java)import java.rmi.Naming;import java.rmi.registry.LocateRegistry;public class HelloServer {/** 启动RMI注册服务并进行对象注册  */public static void main(String args[]) {try{LocateRegistry.createRegistry(1099);HelloInterface hello = new Hello("Hello, world!");Naming.rebind("Hello", hello);//如果要把hello实例注册到另一台启动了RMI注册服务的机器上//Naming.rebind("//192.168.1.105:1099/Hello", hello);System.out.println("Hello Server is ready");} catch(Exception e) {System.out.println("Hello Server failed: " + e);}}}//备注

//客户端查找远程对象,并调用远程方法(HelloClient)import java.rmi.Naming;public class HelloClient {/** 查找远程对象并调用远程方法  */public static void main(String[] argv) {try{HelloInterface hello = (HelloInterface) Naming.lookup("Hello");//如果要从另一台启动了RMI注册服务的机器上查找hello实例//HelloInterface hello=(HelloInterface)Naming.lookup("//192.168.1.105:1099/Hello");//调用远程方法System.out.println(hello.say());} catch(Exception e) {System.out.println("HelloClient exception: " + e);}}}


客户端查找远程对象,并调用远程方法,在客户端输出Hello, world!  在服务器端输出Called by HelloClient



内存映射

在 Windows中内存映射文件可以是脱离物理文件而存在的一块命名的内存区域,使用相同的内存映射名就能在不同的进程中共享同一片内存。然后,Java NIO的内存映射文件(MappedByteBuffer)总是与某个物理文件相关的,因为不管你是从 FileInputStream、FileOutputStream还是 RandomAccessFile 得来的 FileChannel,再 map() 得到的内存映射文件 MappedByteBuffer,如果在构造FileInputStream、FileOutputStream、RandomAccessFile 对象时不指定物理文件便会有FileNotFoundException 异常。
            所以 Java NIO来实现共享内存的办法就是让不同进程的内存映射文件关联到同一个物理文件,因为 MappedByteBuffer能让内存与文件即时的同步内容。严格说来,称之为内存共享是不准确的,其实就是两个 Java进程通过中间文件来交换数据,用中间文件使得两个进程的两块内存区域的内容得到及时的同步。


知道了实现原理之后,下面用代码来演示两个进程间用内存映射文件来进行数据通信。
    代码 WriteShareMemory.java往映射文件中依次写入 A、B、C ... Z。
         ReadShareMemory.java逐个读出来,打印到屏幕上。代码对交换文件 swap.mm 的第一个字节作了读写标志,分别是 0-可读,1-正在写,2-可读。RandomAccessFile得到的 Channel 能够灵活的进行读或写,并且不会破坏原有文件内容,而 FileInputStream 或 FileOutputStream 取得的Channel 则很难达到这一功效,所以使用了 RandomAccessFile 来获得 FileChannel。

WriteShareMemory.java往映射文件中依次写入 A、B、C ... Z。
<pre name="code" class="java">import java.io.RandomAccessFile;import java.nio.MappedByteBuffer;import java.nio.channels.FileChannel;import java.nio.channels.FileChannel.MapMode;public class WriteShareMemory{public static void main(String args[]) throws Exception {//获得一个只读的随机存取文件对象RandomAccessFile raf = new RandomAccessFile("D:/1.mm", "rw");//获得相应的文件通道FileChannel fc = raf.getChannel();//获得共享内存缓冲区,可读写MappedByteBuffer mbb = fc.map(MapMode.READ_WRITE, 0, 1024);for(int i=0; i<1024; i++) {mbb.put(i, (byte)0);}for(int i=65; i<91; i++) {int index = i-63;//从文件的第二个字节开始,依次写入A-Z字母,第一个字节指明了当前操作的位置int flag = mbb.get(0);//可读标志第一个字节为0;if(flag != 0) {i--;continue;}mbb.put(0, (byte)1);//正在写数据,标志第一个字节为1mbb.put(1, (byte)(index));//写数据的位置System.out.println("程序 WriteShareMemory:" + System.currentTimeMillis() + ": 位置: " + index + " 写入数据:" + (char)i);mbb.put(index, (byte)i);mbb.put(0, (byte)2);Thread.sleep(513);}}}

ReadShareMemory.java逐个读出来,打印到屏幕上。
<pre name="code" class="java">import java.io.RandomAccessFile;import java.nio.MappedByteBuffer;import java.nio.channels.FileChannel;import java.nio.channels.FileChannel.MapMode;public class ReadShareMemory {public static void main(String args[]) throws Exception {RandomAccessFile raf = new RandomAccessFile("D:/1.mm", "rw");FileChannel fc = raf.getChannel();MappedByteBuffer mbb = fc.map(MapMode.READ_WRITE, 0,1024);int lastIndex = 0;for(int i=1; i<27; i++) {int flag = mbb.get(0);  //取读写数据的标志  int index = mbb.get(1);//读取数据的位置,2为可读if(flag != 2 || index == lastIndex) {  //加入不可读,或未写入新数据时重复循环i--;  continue;}lastIndex = index;System.out.println("程序 ReadShareMemory:" + System.currentTimeMillis() + ":位置: " + index + " 读出数据:" + (char)mbb.get(index));mbb.put(0, (byte)0);//置第一个字节为可读标志为0if(index == 27) {//读完数据后退出break;}}}}


管道

•Java程序中可以启动其他的应用程序,这种在Java中启动的进程称为子进程,启动子进程的Java程序称为父进程,其实这个父进程就是一个Java虚拟机。在Java程序中可以用Process类的实例对象来表示子进程,子进程的标准输入和输出不在连接到键盘和显示器(也就是不再接收键盘输入,和显示器输出),而是以管道流的形式连接到父进程的一个输出流和输入流对象上。
•调用Process类的getOutputStream和getInputStream方法可以获得连接到子进程的输出流和输入流对象。子进程从标准输入读到的内容就是父进程通过输出流对象写入到它们俩之间的进程管道中的数据,子进程写入的标准输出的数据通过它们之间的进程管道传递到了父进程的输入流对象中,父进程从这个输入流对象中读取到的内容就是子进程写入到标准输出的数据编程实例。

以下程序在TestInOut类中启动java.exe命令执行另外一个MyTest类,TestInOut和MyTest通过进程间的管道互相传递数据。TestInOut启动两个线程,一个不停的向MyTest中发送数据,另一个它不听的读取MyTest写会的数据。

TestInOut程序如下:

import java.io.*;class TestInOut implements Runnable {Process p = null;public TestInOut() throws Exception {p = Runtime.getRuntime().exec("java MyTest");  //启动子进程,这个程序不存在会出现问题!new Thread(this).start(); }public void send() throws Exception {int i=0;try{OutputStream ops = p.getOutputStream();  //发送,首先要连接一个输出流对象while(true) {i++;System.out.println("" + i);if(i > 1000) {break;}ops.write(("help\r\n"+(new Integer(i)).toString()).getBytes());  //写入字符串}} catch(Exception e) {e.printStackTrace();}}public void run() {try{InputStream in = p.getInputStream();BufferedReader bfr = new BufferedReader(newInputStreamReader(in));while(true) {String strLine = bfr.readLine();System.out.println(strLine);}} catch(Exception e) {e.printStackTrace();}}public static void main(String args[]) throws Exception {TestInOut ts = new TestInOut();//创建对象时,子进程就启动了,接收线程启动了。ts.send();}}


<pre name="code" class="java"><pre name="code" class="java"><pre name="code" class="java"><pre name="code" class="java">import java.io.*;public class MyTest {public static void main(String args[]) {BufferedReader bfr = new BufferedReader(new InputStreamReader(System.in));while(true) {try{String strLine = bfr.readLine();if(strLine != null) {System.out.println("hi:" + strLine);} elsereturn ;} catch(Exception e) {e.printStackTrace();}}}}
允许TestInOut.java程序后的结果






0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 你能利用你的弱点打击你怎么办 研控两相混合伺服电机反转怎么办? 战地一要我升级显卡驱动怎么办 刺客信条兄弟会存档损坏了怎么办 电脑上所有软件和文件被删了怎么办 电脑显示文件已打开无法删除怎么办 金立手机桌面停止运行黑屏怎么办 苹果平板电脑玩游戏黑屏闪退怎么办 电脑开机时显示无法找到入口怎么办 我的世界显示网络玩不了的怎么办啊 网页被设置成不可以到下一页怎么办 小天鹅热水器排污螺丝拧不动怎么办 葡萄霜霉严重叶片开始发焦了怎么办 上海高架gps定位信号差怎么办 老公开车技术不行还非要开怎么办 我偷了同学手机被发现应该怎么办 没满月孩孑4天没大便了怎么办 电机轴总是从皮带轮处断裂怎么办 天花板吊顶里的热水管经常坏怎么办 摩托车油箱下面的废油管漏油怎么办 大修机械压力机轴取不下来怎么办 萌侠传说账号密码没了怎么办 车子前保护杠塑料刮花了怎么办 糖猫电话手表关机了找不到了怎么办 小天才电话手表被洗衣机洗了怎么办 小天才电话手表放洗衣机洗了怎么办 小天才电话手表泡水了怎么办 小天才电话手表联不上网怎么办 肺炎用激素治疗后肚子大了怎么办 8岁以下儿童总是低烧不退怎么办? 微博里面的视频不能改变方向怎么办 朗逸导航倒车一体机死机了怎么办 乐淘乐电话手表的二维码没了怎么办 艾蔻儿童手表二维码丢了怎么办 糖猫儿童智能手表二维码丢了怎么办 海信电视用遥控器关了打不开怎么办 创维4k电视遥控器按键坏了怎么办 大疆3s云台陀螺仪错误怎么办 无线路由我用手机上网网速慢怎么办 下载的软件安装包以丢失怎么办 战舰世界航母的飞机恐惧状态怎么办