我正在编写一个java程序,以便在另一个线程中对服务器进行HTTP调用。以下代码我在线程池执行器中的单独Callable任务中执行。
public static class MyRunnable implements Callable<Boolean>{
@Override
public Boolean call() {
HttpURLConnection conn = null;
try {
URL url = new URL("http://www.myserver.com");
conn = (HttpURLConnection) url.openConnection();
conn.setConnectTimeout(5000);
conn.setReadTimeout(5000);
conn.setRequestMethod("GET");
int response = conn.getResponseCode();
return response == 200;
}
catch (IOException e) {
e.printStackTrace();
return false;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
}
由于某种原因,服务器没有响应或服务器响应非常慢。由于此服务器的行为,连接超时和读取超时都不会发生。
因此,我希望监视此任务(在线程池执行程序中运行),并在一段时间后中断该线程,并确保从池中删除此任务,以便线程池不包含此任务并释放所有资源采取这个线程。
我尝试了Future
的java,如下面的
ThreadPoolExecutor tpe = new ThreadPoolExecutor(2, 5, 5, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(10));
Future<Boolean> f = tpe.submit(new MyRunnable());
try {
Boolean success = f.get(5000, TimeUnit.MILLISECONDS);
} catch (Exception e) {
e.printStackTrace();
}
使用此代码,如果正在处理TimeoutException
任务的线程没有响应,则在5000毫秒后从f.get
调用获得MyRunnable
。但我可以看到,如果任务停留在HttpURLConnection.getResponseCode()
,该任务将继续在线程池执行器中运行。
当我尝试f.cancel(true)
时,当任务停留在HttpURLConnection.getResponseCode()
方法调用时,它不会中断线程。我知道线程只有在下一个可用机会中测试时才会被中断。因此,我猜future.cancel
在这种情况下无效。
那么我如何从这个调用中解脱出来(通过与线程池执行器交互)并确保从池中删除任务并且相应的线程可以自由处理不同的任务?
感谢您提前回复。
谢谢,
Raagu
答案 0 :(得分:0)
我认为你可以与另一个在超时后调用disconnect()的线程共享连接。所以,它应该是这样的:
static class ConnectionStopper implements Runnable {
private final HttpURLConnection conn;
ConnectionStopper(HttpURLConnection conn) {
if (conn == null) {
throw new NullPointerException();
}
this.conn = conn;
}
@Override
public void run() {
conn.disconnect();
}
}
...
ScheduledExecutorService service = Executors.newScheduledThreadPool(THREAD_POOL_SIZE);
...
// Submit your MyRunnable, then schedule a ConnectionStopper
service.schedule(new ConnectionStopper(conn), 5, TimeUnit.SECONDS);
答案 1 :(得分:0)
在超时异常的情况下调用Future.cancel(true)。这将中断您在runnable中所做的工作。这应该导致conn.getResponseCode()在你的callable中抛出InterruptedIOException。