问题描述:
A线程调用WS的B方法,并且获取B方法的返回值。
情境一:
A线程连接时无法连接上WS,程序报错,正常执行下去。
情境二:
A线程连接上WS,并且执行B方法,在B方法返回前,A与WS之间出现网络异常或其他原因造成A无法获取B方法的返回值,那么A会一直无限等待。。。
调查过程:
使用jstack 来把程序的线程输出,找到对应的线程,以下是线程的内容:
"main" prio=6 tid=0x00000000005ce800 nid=0x3658 runnable [0x0000000001d0e000..0x0000000001d0fc50]
java.lang.Thread.State: RUNNABLE
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.read(SocketInputStream.java:129)
at java.io.BufferedInputStream.fill(BufferedInputStream.java:218)
at java.io.BufferedInputStream.read(BufferedInputStream.java:237)
- locked <0x0000000049f1bc98> (a java.io.BufferedInputStream)
at org.apache.commons.httpclient.HttpParser.readRawLine(HttpParser.java:77)
at org.apache.commons.httpclient.HttpParser.readLine(HttpParser.java:105)
at org.apache.commons.httpclient.HttpConnection.readLine(HttpConnection.java:1115)
at org.apache.commons.httpclient.MultiThreadedHttpConnectionManager$HttpConnectionAdapter.readLine(MultiThreadedHttpConnectionManager.java:1373)
at org.apache.commons.httpclient.HttpMethodBase.readStatusLine(HttpMethodBase.java:1832)
at org.apache.commons.httpclient.HttpMethodBase.readResponse(HttpMethodBase.java:1590)
at org.apache.commons.httpclient.HttpMethodBase.execute(HttpMethodBase.java:995)
at org.apache.commons.httpclient.HttpMethodDirector.executeWithRetry(HttpMethodDirector.java:397)
at org.apache.commons.httpclient.HttpMethodDirector.executeMethod(HttpMethodDirector.java:170)
at org.apache.commons.httpclient.HttpClient.executeMethod(HttpClient.java:396)
at org.codehaus.xfire.transport.http.CommonsHttpMessageSender.send(CommonsHttpMessageSender.java:369)
at org.codehaus.xfire.transport.http.HttpChannel.sendViaClient(HttpChannel.java:123)
at org.codehaus.xfire.transport.http.HttpChannel.send(HttpChannel.java:48)
at org.codehaus.xfire.handler.OutMessageSender.invoke(OutMessageSender.java:26)
at org.codehaus.xfire.handler.HandlerPipeline.invoke(HandlerPipeline.java:131)
at org.codehaus.xfire.client.Invocation.invoke(Invocation.java:79)
at org.codehaus.xfire.client.Invocation.invoke(Invocation.java:114)
at org.codehaus.xfire.client.Client.invoke(Client.java:336)
at org.codehaus.xfire.client.Client.invoke(Client.java:368)
at test.TestTimeOut.main(TestTimeOut.java:32)
解决方法:
设置读取超时时间。
conn = (HttpURLConnection)url.openConnection();
conn.setReadTimeout(5000);
conn.setConnectTimeout(5000);
client = new Client(conn.getInputStream(),null);
//设置发送的超时限制,单位是毫秒,30秒;
client.setProperty(CommonsHttpMessageSender.HTTP_TIMEOUT, String.valueOf( 30000 ));
client.setProperty(CommonsHttpMessageSender.DISABLE_KEEP_ALIVE, "true");
client.setProperty(CommonsHttpMessageSender.DISABLE_EXPECT_CONTINUE, "true");
或者
Service serviceModel = objectServiceFactory.create(Class.forName(interfaceName));
// 设置读取超时时间30秒
serviceModel.setProperty(CommonsHttpMessageSender.HTTP_TIMEOUT, String.valueOf( 30000 ));
serviceModel.setProperty(CommonsHttpMessageSender.DISABLE_KEEP_ALIVE, "true");
serviceModel.setProperty(CommonsHttpMessageSender.DISABLE_EXPECT_CONTINUE, "true");
Object service = xfireProxyFactory.create(serviceModel,url);