【发布时间】:2016-02-04 13:59:15
【问题描述】:
我编写了测试 RMI 服务器和客户端程序。在服务器中,有一种方法向客户端公开。
在客户端,我正在使用一个 600 线程的执行器服务来调用 RMI 方法 6000 次。
在服务端,每个方法调用都会创建一个简单的任务,并提交给一个300线程的执行器服务。
每次执行时我都会遇到一两次异常。因此,对于 6000 次调用,我得到大约 1 到 3 个异常。此外,这些例外似乎只发生在初始加速阶段。
java.rmi.ConnectIOException: Exception creating connection to: ; nested exception is:
java.net.SocketException: Connection reset by peer
at sun.rmi.transport.tcp.TCPEndpoint.newSocket(TCPEndpoint.java:631)
at sun.rmi.transport.tcp.TCPChannel.createConnection(TCPChannel.java:216)
at sun.rmi.transport.tcp.TCPChannel.newConnection(TCPChannel.java:202)
at sun.rmi.server.UnicastRef.invoke(UnicastRef.java:129)
at java.rmi.server.RemoteObjectInvocationHandler.invokeRemoteMethod(RemoteObjectInvocationHandler.java:194)
at java.rmi.server.RemoteObjectInvocationHandler.invoke(RemoteObjectInvocationHandler.java:148)
at com.sun.proxy.$Proxy0.receiveMessage(Unknown Source)
at com.example.rmi.MsgTask.run(MsgTask.java:18)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)
at java.util.concurrent.FutureTask.run(FutureTask.java:262)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:744)
客户端和服务器运行在同一台机器上,同一个 Eclipse IDE。
看起来如果 rmi 服务器程序在收到请求时忙了几毫秒,则请求可能会被丢弃。这个可以吗?我是否应该将此行为视为正常行为并在将来在我的 RMI 客户端中构建“重试”方法?或者,我可以更改一些设置以确保请求不会被丢弃吗?
【问题讨论】:
-
看起来在 RMI 服务器端对象中收到的每个调用都在一个单独的线程上。因此,无需在服务器端使用手动线程。虽然,如果留给“自动”,线程数似乎没有上限。
-
没那么简单。 RMI 规范在这一点上故意模糊不清,但您可以从它所说的内容中得到一件事,即您不能假设 RMI 服务器是单线程的。您在 Sun/Oracle JDK 中真正得到的是每个连接一个线程。
标签: java multithreading rmi