在我的Android应用程序中,我有一些代码:
while(testCase){
for(HttpPut put : httpPut){
try {
httpclient.execute(put, responseHandler);
} catch (ClientProtocolException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
try {
Thread.sleep(150);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
我的目标是在一个永久循环中按顺序每隔150毫秒发出一个预先构建的HTTPPut请求列表(在这种情况下:“httpPut”),直到被告知中断(由“testCase”boolean打破) 。它在技术上有效,但实际执行中有时会有很多延迟。在每个请求的接收端,它可能会在收到另一个HTTPPut之前滞后3-5秒。而手机的屏幕关闭甚至更糟。我在扩展的AsyncTask类中运行此代码。
我的问题是,在执行此代码时,我可以通过哪种方式更有效地以更精确的方式触发代码;准确地接近每150毫秒?谢谢你的阅读!
修改 建议在另一个线程中运行,我尝试添加此代码:
...
performOnBackgroundThread(new Runnable(){
@SuppressWarnings("unchecked")
@Override
public void run() {
try {
final DefaultHttpClient httpclient = new DefaultHttpClient();
final ResponseHandler responseHandler = new BasicResponseHandler();
httpclient.execute(put, responseHandler);
} catch (ClientProtocolException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
});
...
public static Thread performOnBackgroundThread(final Runnable runnable) {
final Thread t = new Thread() {
@Override
public void run() {
try {
runnable.run();
} finally {
}
}
};
t.start();
return t;
}
但是我的应用程序很快崩溃了“I / Process(18762):发送信号.PID:18762 SIG:9”我也得到了一堆这些错误。
02-10 00:14:58.639: W/SingleClientConnManager(18762): Invalid use of SingleClientConnManager: connection still allocated.
02-10 00:14:58.639: W/SingleClientConnManager(18762): Make sure to release the connection before allocating another one.
02-10 00:14:58.639: W/SingleClientConnManager(18762): Invalid use of SingleClientConnManager: connection still allocated.
02-10 00:14:58.639: W/SingleClientConnManager(18762): Make sure to release the connection before allocating another one.
02-10 00:14:58.647: W/System.err(18762): java.net.SocketException: Socket closed
02-10 00:14:58.647: W/System.err(18762): at libcore.io.Posix.recvfromBytes(Native Method)
02-10 00:14:58.647: W/System.err(18762): at libcore.io.Posix.recvfrom(Posix.java:131)
02-10 00:14:58.647: W/System.err(18762): at libcore.io.BlockGuardOs.recvfrom(BlockGuardOs.java:164)
02-10 00:14:58.647: W/System.err(18762): at libcore.io.IoBridge.recvfrom(IoBridge.java:513)
02-10 00:14:58.647: W/System.err(18762): at java.net.PlainSocketImpl.read(PlainSocketImpl.java:488)
02-10 00:14:58.647: W/System.err(18762): at java.net.PlainSocketImpl.access$000(PlainSocketImpl.java:46)
02-10 00:14:58.647: W/System.err(18762): at java.net.PlainSocketImpl$PlainSocketInputStream.read(PlainSocketImpl.java:240)
02-10 00:14:58.647: W/System.err(18762): at org.apache.http.impl.io.AbstractSessionInputBuffer.fillBuffer(AbstractSessionInputBuffer.java:103)
02-10 00:14:58.655: W/System.err(18762): at org.apache.http.impl.io.AbstractSessionInputBuffer.readLine(AbstractSessionInputBuffer.java:191)
02-10 00:14:58.655: W/System.err(18762): at org.apache.http.impl.conn.DefaultResponseParser.parseHead(DefaultResponseParser.java:82)
02-10 00:14:58.655: W/System.err(18762): at org.apache.http.impl.io.AbstractMessageParser.parse(AbstractMessageParser.java:174)
02-10 00:14:58.655: W/System.err(18762): at org.apache.http.impl.AbstractHttpClientConnection.receiveResponseHeader(AbstractHttpClientConnection.java:180)
02-10 00:14:58.655: W/System.err(18762): at org.apache.http.impl.conn.DefaultClientConnection.receiveResponseHeader(DefaultClientConnection.java:235)
02-10 00:14:58.663: W/System.err(18762): at org.apache.http.impl.conn.AbstractClientConnAdapter.receiveResponseHeader(AbstractClientConnAdapter.java:259)
02-10 00:14:58.663: W/System.err(18762): at org.apache.http.protocol.HttpRequestExecutor.doReceiveResponse(HttpRequestExecutor.java:279)
02-10 00:14:58.663: W/System.err(18762): at org.apache.http.protocol.HttpRequestExecutor.execute(HttpRequestExecutor.java:121)
02-10 00:14:58.663: W/System.err(18762): at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:428)
02-10 00:14:58.663: W/System.err(18762): at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:555)
02-10 00:14:58.663: W/System.err(18762): at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:653)
02-10 00:14:58.663: W/System.err(18762): at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:627)
02-10 00:14:58.663: W/System.err(18762): at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:616)
02-10 00:14:58.663: W/System.err(18762): at com.<takenout>.<takenout>.<takenout>.run(MyFile.java:79)
02-10 00:14:58.663: W/System.err(18762): at com.<takenout>.<takenout>.<takenout>.run(MyFile.java:116)
02-10 00:14:58.671: W/System.err(18762): java.net.SocketTimeoutException
02-10 00:14:58.671: W/System.err(18762): at java.net.PlainSocketImpl.read(PlainSocketImpl.java:491)
02-10 00:14:58.671: W/System.err(18762): at java.net.PlainSocketImpl.access$000(PlainSocketImpl.java:46)
02-10 00:14:58.671: W/dalvikvm(18762): threadid=17: thread exiting with uncaught exception (group=0x40d03300)
编辑#2:
02-10 00:38:08.639: W/System.err(20100): java.net.SocketException: recvfrom failed: ECONNRESET (Connection reset by peer)
02-10 00:38:08.639: W/System.err(20100): at libcore.io.IoBridge.maybeThrowAfterRecvfrom(IoBridge.java:552)
02-10 00:38:08.639: W/System.err(20100): at libcore.io.IoBridge.recvfrom(IoBridge.java:516)
02-10 00:38:08.639: W/System.err(20100): at java.net.PlainSocketImpl.read(PlainSocketImpl.java:488)
02-10 00:38:08.647: W/System.err(20100): at java.net.PlainSocketImpl.access$000(PlainSocketImpl.java:46)
02-10 00:38:08.647: W/System.err(20100): at java.net.PlainSocketImpl$PlainSocketInputStream.read(PlainSocketImpl.java:240)
02-10 00:38:08.647: W/System.err(20100): at org.apache.http.impl.io.AbstractSessionInputBuffer.fillBuffer(AbstractSessionInputBuffer.java:103)
02-10 00:38:08.647: W/System.err(20100): at org.apache.http.impl.io.AbstractSessionInputBuffer.readLine(AbstractSessionInputBuffer.java:191)
02-10 00:38:08.647: W/System.err(20100): at org.apache.http.impl.conn.DefaultResponseParser.parseHead(DefaultResponseParser.java:82)
02-10 00:38:08.647: W/System.err(20100): at org.apache.http.impl.io.AbstractMessageParser.parse(AbstractMessageParser.java:174)
02-10 00:38:08.647: W/System.err(20100): at org.apache.http.impl.AbstractHttpClientConnection.receiveResponseHeader(AbstractHttpClientConnection.java:180)
02-10 00:38:08.647: W/System.err(20100): at org.apache.http.impl.conn.DefaultClientConnection.receiveResponseHeader(DefaultClientConnection.java:235)
02-10 00:38:08.647: W/System.err(20100): at org.apache.http.impl.conn.AbstractClientConnAdapter.receiveResponseHeader(AbstractClientConnAdapter.java:259)
02-10 00:38:08.647: W/System.err(20100): at org.apache.http.protocol.HttpRequestExecutor.doReceiveResponse(HttpRequestExecutor.java:279)
02-10 00:38:08.647: W/System.err(20100): at org.apache.http.protocol.HttpRequestExecutor.execute(HttpRequestExecutor.java:121)
02-10 00:38:08.647: W/System.err(20100): at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:428)
02-10 00:38:08.647: W/System.err(20100): at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:555)
02-10 00:38:08.647: W/System.err(20100): at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:653)
02-10 00:38:08.647: W/System.err(20100): at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:627)
02-10 00:38:08.647: W/System.err(20100): at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:616)
02-10 00:38:08.647: W/System.err(20100): at com.<takenout>.<takenout>.<takenout>.run(MyFile.java:79)
02-10 00:38:08.647: W/System.err(20100): at com.<takenout>.<takenout>.<takenout>.run(MyFile.java:116)
02-10 00:38:08.647: W/System.err(20100): Caused by: libcore.io.ErrnoException: recvfrom failed: ECONNRESET (Connection reset by peer)
02-10 00:38:08.647: W/System.err(20100): at libcore.io.Posix.recvfromBytes(Native Method)
02-10 00:38:08.647: W/System.err(20100): at libcore.io.Posix.recvfrom(Posix.java:131)
02-10 00:38:08.647: W/System.err(20100): at libcore.io.BlockGuardOs.recvfrom(BlockGuardOs.java:164)
02-10 00:38:08.647: W/System.err(20100): at libcore.io.IoBridge.recvfrom(IoBridge.java:513)
02-10 00:38:08.647: W/System.err(20100): ... 19 more
答案 0 :(得分:2)
由于网络指标存在差异,您实际上无法100%保证您的服务器每150毫秒会更新一次。你最好的选择是尝试比你想要的更快的东西,例如:每隔100ms发送一个新请求,并希望服务器至少每100ms收到一次更新。此外,如果您要快速发送请求,请考虑使用UDP over TCP。由于确保数据包交付的开销,TCP请求在我的经验中花费的时间更长,但是如果您丢失了一两个,如果您的平均案例性能要好得多,那么对您来说并不是一件大事。 90%的情况下,您每100毫秒看到一次更新。
您可能会在服务器上看到延迟,因为您遇到了早先的请求,例如如果req1需要200ms,req2需要350ms,req3需要120ms,那么在服务器上你不会每隔150ms看到一次请求。对于前几个请求尤其如此,其中网络性能可能在5-10个请求之后显着更差(例如1-2秒)。
我建议您创建第二个AsyncTask类,您可以从第一个AsyncTask快速生成(请参阅this获取一些可能的指导)。但是,如果您如此快速地生成新的请求对象,这可能只会让您最终遇到一些线程限制。
最大的问题是你确定你做的是正确的吗?你不会让网络芯片组在请求之间有150毫秒的差距(这可能需要超过150毫秒才能完成执行!),所以为什么甚至打扰许多个别请求?为什么不使用像套接字一样保持开放的东西(例如google http long polling)?