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。
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
- java进程间通讯机制代码
- 进程间通讯机制!
- 转载:进程间通讯机制
- Linux进程间通讯机制
- handler进程间通讯机制
- Linux 核心--6.进程间通讯机制
- Linux 核心--.进程间通讯机制
- 使用内存共享机制进程间通讯
- Android IPC进程间通讯机制
- Android IPC进程间通讯机制
- Android IPC进程间通讯机制
- 使用内存共享机制进程间通讯
- Android系统进程间通讯Binder机制
- Linux进程间通讯四--信号量通讯机制
- 进程间通讯-共享内存2(代码)
- Java使用管道实现进程间通讯
- java 进程间通讯的有几种方法?
- java 进程间通讯的有几种方法?
- 【转】大学毕业初感悟
- 在车站的垃圾堆边看见了我
- 外媒:越南称中国钻井平台向东南偏东方向转移(1)
- sscanf的用法
- Android 自定义View 中的OnMeasure的用法
- java进程间通讯机制代码
- 黑马程序员_Java网络编程之TCP应用
- 基于GTK+的单词数值计算器
- 3.Swift教程翻译系列——Swift基础知识
- java枚举在android项目应用
- poj 2718 Smallest Difference
- js 阻止元素(文档)默认事件,阻止冒泡事件
- 移动终端,一个凑单的想法
- java枚举在android项目应用