当我编写一个简单的rpc程序时,遇到了一个奇怪的问题!我的英语不好,请检查代码...
以下代码可以正常工作,但是当我交换位于类try-with-block
的{{1}}中的 A 和 B 的顺序时,
他们封锁了...
RpcImporter
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
package demo1;
public interface EchoService {
String echo(String ping);
}
那么,为什么会发生这种情况?
答案 0 :(得分:2)
来自Java文档:
ObjectInputStream
:
ObjectInputStream创建一个ObjectInputStream,该对象从 指定的InputStream。 从流中读取并验证序列化流头。 该构造函数将阻塞,直到对应的ObjectOutputStream 已经写入并刷新了标题。
ObjectOutputStream
:
ObjectOutputStream创建一个ObjectOutputStream写入指定的 OutputStream。该构造函数编写序列化流头 到底层流;呼叫者可能希望刷新流 立即确保要接收的构造函数 读取标头时,ObjectInputStreams不会阻塞。
如您所见,它明确表示如果ObjectOutputStream
构造函数未先调用,则ObjectInputStream
构造函数将被阻止
换句话说,这是2个特殊资源,必须先按顺序调用(ObjectOutputStream
构造函数),否则ObjectInputStream
构造函数将阻塞
(如果您正在使用1个线程...)