Java попробуй с ресурсом. Заказ ресурсов - PullRequest
0 голосов
/ 03 сентября 2018

Когда я пишу простую программу rpc, я столкнулся со странной проблемой! Мой английский плохой, пожалуйста, проверьте код ... код ниже работает правильно, но когда я поменяю местами порядок A и B , который находится в try-with-block класса RpcImporter, они заблокировали ...

  1. RpcImporter


    package demo1;

    import java.io.ObjectInputStream;
    import java.io.ObjectOutputStream;
    import java.lang.reflect.Proxy;
    import java.net.InetSocketAddress;
    import java.net.Socket;

    public class RpcImporter {
        public S importer(final Class serviceClass, final InetSocketAddress address) {
            return (S) Proxy.newProxyInstance(
                    serviceClass.getClassLoader(),
                    new Class[]{serviceClass.getInterfaces()[0]},
                    (proxy, method, args) -> {

                        try (Socket socket = new Socket(address.getHostName(), address.getPort());
                             // this is A
                             ObjectOutputStream output = new ObjectOutputStream(socket.getOutputStream()); 
                             // this is B
                             ObjectInputStream input = new ObjectInputStream(socket.getInputStream()); 
                             ) {
                            System.out.println("start request");
                            output.writeUTF(serviceClass.getName());
                            output.writeUTF(method.getName());
                            output.writeObject(method.getParameterTypes());
                            output.writeObject(args);
                            return input.readObject();
                        }

                    });

        }
    }

  1. RpcExporter


    package demo1;

    import java.io.IOException;
    import java.io.ObjectInputStream;
    import java.io.ObjectOutputStream;
    import java.lang.reflect.Method;
    import java.net.ServerSocket;
    import java.net.Socket;
    import java.util.Calendar;
    import java.util.concurrent.Executor;
    import java.util.concurrent.Executors;

    public class RpcExporter {
        static Executor executor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());

        public static void exporter(int port) throws IOException {

            try (ServerSocket serverSocket = new ServerSocket(port)) {
                while (true) {
                    executor.execute(new ExporterTask(serverSocket.accept()));
                }
            }
        }

        private static class ExporterTask implements Runnable {
            final Socket socket;

            public ExporterTask(Socket socket) {
                this.socket = socket;
            }

            @Override
            public void run() {
                try (ObjectInputStream input = new ObjectInputStream(socket.getInputStream());
                     ObjectOutputStream output = new ObjectOutputStream(socket.getOutputStream());
                ) {
                    String interfaceName = input.readUTF();
                    Class service = Class.forName(interfaceName);
                    String methodName = input.readUTF();
                    Class[] parameterTypes = (Class[]) input.readObject();
                    Object[] arguments = (Object[]) input.readObject();
                    Method method = service.getMethod(methodName, parameterTypes);
                    Object result = method.invoke(service.newInstance(), arguments);
                    output.writeObject(result);
                }catch (Exception e){
                    e.printStackTrace();
                }
            }
        }
    }

  1. RpcTest


    package demo1;


    import java.io.IOException;
    import java.net.InetSocketAddress;

    public class RpcTest {

        public static void main(String[] args) throws Exception {
            new Thread(() -> {
                try {
                    RpcExporter.exporter(38088);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }).start();

            RpcImporter importer = new RpcImporter();
            EchoService echoService = importer.importer(EchoServiceImpl.class, new InetSocketAddress("localhost", 38088));
            System.out.println(echoService.echo("Are you ok ?"));
        }
    }

  1. EchoServiceImpl


    package demo1;


    import java.io.IOException;
    import java.net.InetSocketAddress;

    public class RpcTest {

        public static void main(String[] args) throws Exception {
            new Thread(() -> {
                try {
                    RpcExporter.exporter(38088);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }).start();

            RpcImporter importer = new RpcImporter();
            EchoService echoService = importer.importer(EchoServiceImpl.class, new InetSocketAddress("localhost", 38088));
            System.out.println(echoService.echo("Are you ok ?"));
        }
    }

  1. EchoService

    
    package demo1;</p>
    
    <p>public interface EchoService {
        String echo(String ping);
    }</p></li>
    </ol>
    
    <p>

    Итак, почему это могло произойти?

1 Ответ

0 голосов
/ 03 сентября 2018

из документа Java:

ObjectInputStream * * 1004

ObjectInputStream Создает ObjectInputStream, который читает из указанный InputStream. Заголовок потока сериализации считывается из потока и проверяется. Этот конструктор будет блокироваться до соответствующего ObjectOutputStream написал и очистил заголовок.

ObjectOutputStream:

ObjectOutputStream Создает ObjectOutputStream, который записывает в указанный OutputStream. Этот конструктор записывает заголовок потока сериализации в основной поток; вызывающие абоненты могут захотеть очистить поток немедленно убедиться, что конструкторы для получения ObjectInputStreams не будет блокироваться при чтении заголовка.

так что, как вы можете видеть, это явно говорит о том, что если конструктор ObjectOutputStream не вызывает сначала, конструктор ObjectInputStream будет заблокирован

другими словами, это 2 специальных ресурса, которые должны вызываться в порядке (сначала конструктор ObjectOutputStream), иначе конструктор ObjectInputStream заблокирует

(если вы используете 1 поток ...)

...