Java 进程间通讯的几种方式

Java FileLock 面试 大约 3343 字

IPC

进程间通讯:InterProcess Communication。不同进程间的数据读写。

Socket 方式

HTTPTCPRPC等可以实现直接的数据交换。

MQ 方式

RabbitMQRocketMQKafka等可以实现间接的数据交换。

文件方式

DatebaseFile等可以实现间接的数据交换。

共享内存

Java中通过MappedByteBuffer共享内存来实现进程间通讯。

本质是对文件的读写,为避免高并发下的数据错乱,可使用FileLock文件锁对文件加锁操作。

public class WriteShareMemory {

    public static void main(String[] args) {
        try (RandomAccessFile randomAccessFile = new RandomAccessFile("share.mm", "rw")) {
            FileChannel channel = randomAccessFile.getChannel();
            FileLock lock = channel.lock();

            MappedByteBuffer buffer = channel.map(FileChannel.MapMode.READ_WRITE, 0, 10);
            for (int i = 0; i < 10; i++) {
                buffer.put(i, (byte) i);
                Thread.sleep(2000);
            }
            lock.release();
        } catch (IOException | InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("写入完成");
    }

}

public class ReadShareMemory {

    public static void main(String[] args) {
        try (RandomAccessFile randomAccessFile = new RandomAccessFile("share.mm", "rw")) {
            FileChannel channel = randomAccessFile.getChannel();
            MappedByteBuffer buffer = channel.map(FileChannel.MapMode.READ_WRITE, 0, 10);

            FileLock lock;

            while (true) {
                lock = channel.tryLock();
                if (lock == null) {
                    Thread.sleep(2000);
                    System.out.println("locked");
                } else {
                    break;
                }
            }

            for (int i = 0; i < 10; i++) {
                System.out.println(buffer.get(i));
            }
            lock.release();
        } catch (IOException | InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("读取完成");
    }

}

RMI 方式

Remote Method Invoke:远程方法调用。可以实现直接的数据交换。

public interface IRemote extends Remote {
    String testMethod(String a, String b) throws RemoteException;
}

public class RemoteBean extends UnicastRemoteObject implements IRemote {
    private static final long serialVersionUID = 3682470187378911418L;

    protected RemoteBean() throws RemoteException {
    }

    @Override
    public String testMethod(String a, String b) {
        return a + b;
    }
}

public class RmiServer {

    public static void main(String[] args) {
        try {
            IRemote iRemote = new RemoteBean();
            LocateRegistry.createRegistry(1099);
            Registry registry = LocateRegistry.getRegistry();
            registry.bind("test", iRemote);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}

public class RmiClient {

    public static void main(String[] args) {
        try {
            Registry registry = LocateRegistry.getRegistry("localhost",1099);
            IRemote iRemote = (IRemote) registry.lookup("test");
            String s = iRemote.testMethod("hello", "world");
            System.out.println(s);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}

如果不使用接口对象IRemote将抛出如下异常,原因是Java动态代理是面向接口的:

java.lang.ClassCastException: class com.sun.proxy.$Proxy0 cannot be cast to class RemoteBean (com.sun.proxy.$Proxy0 and RemoteBean are in unnamed module of loader 'app')
    at RmiClient.main(RmiClient.java:12)
阅读 36 · 发布于 2021-04-17

————        END        ————

扫描下方二维码关注公众号和小程序↓↓↓

扫描二维码关注我
昵称:
随便看看 换一批