Java try-with-resource。资源顺序

时间:2018-09-03 08:42:21

标签: java try-with-resources

当我编写一个简单的rpc程序时,遇到了一个奇怪的问题!我的英语不好,请检查代码... 以下代码可以正常工作,但是当我交换位于类try-with-block的{​​{1}}中的 A B 的顺序时, 他们封锁了...

  1. RpcImporter
RpcImporter
  1. 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(); } }); } }
RpcExporter
  1. 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(); } } } }
RpcTest
  1. 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 ?")); } }
EchoServiceImpl
  1. 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 ?")); } }

    EchoService
  2. package demo1;

    public interface EchoService { String echo(String ping); }

那么,为什么会发生这种情况?

1 个答案:

答案 0 :(得分:2)

来自Java文档:

ObjectInputStream

  

ObjectInputStream创建一个ObjectInputStream,该对象从   指定的InputStream。       从流中读取并验证序列化流头。       该构造函数将阻塞,直到对应的ObjectOutputStream       已经写入并刷新了标题。

ObjectOutputStream

  

ObjectOutputStream创建一个ObjectOutputStream写入指定的   OutputStream。该构造函数编写序列化流头   到底层流;呼叫者可能希望刷新流   立即确保要接收的构造函数   读取标头时,ObjectInputStreams不会阻塞。

如您所见,它明确表示如果ObjectOutputStream构造函数未先调用,则ObjectInputStream构造函数将被阻止

换句话说,这是2个特殊资源,必须先按顺序调用(ObjectOutputStream构造函数),否则ObjectInputStream构造函数将阻塞

(如果您正在使用1个线程...)