当我编写一个简单的rpc程序时,我遇到了一个奇怪的问题!我的英语很差,请查一下密码.下面的代码工作正常,但是当我交换A和B的顺序,它们位于RpcImporter类的try-with-block中,它们阻止了.
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();
}
});
}
}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();
}
}
}
}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 ?"));
}
}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 ?"));
}
}EchoService包demo1;公共接口EchoService {字符串回波(字符串ping);}
为什么会发生这种事?
发布于 2018-09-03 14:41:54
来自java文档:
ObjectInputStream
ObjectInputStream创建一个从指定的InputStream读取的ObjectInputStream。从流中读取序列化流头并进行验证。此构造函数将被阻塞,直到相应的ObjectOutputStream编写和刷新了标头。
ObjectOutputStream
ObjectOutputStream创建一个写入指定OutputStream的ObjectOutputStream。此构造函数将序列化流头写入基础流;调用方可能希望立即刷新流,以确保用于接收ObjectInputStreams的构造函数在读取标头时不会阻塞。
因此,正如您所看到的,它明确指出,如果ObjectOutputStream构造函数没有首先调用,ObjectInputStream构造函数将被阻塞。
换句话说,这是两个必须按顺序调用的特殊资源(首先是ObjectOutputStream构造函数),否则ObjectInputStream构造函数将被阻塞。
(如果您使用的是1线程.)
https://stackoverflow.com/questions/52146106
复制相似问题