中断在Java中进行HTTP调用的线程

时间:2014-04-22 07:01:40

标签: java multithreading http threadpoolexecutor

我正在编写一个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

2 个答案:

答案 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