如何杀死发送长时间运行的HTTP请求的线程?

时间:2018-12-14 12:06:20

标签: java multithreading

我有以下Task类,该类将http请求发送到API。如果该过程花费的时间太长,我想通过调用stop函数杀死该线程,但是它不起作用。

class Task implements Runnable{

        private final AtomicReference<Thread> currentThread = new AtomicReference<Thread>();
        private String bid;
        private long id;

        public Task(String bid, long id) {
            this.bid = bid;
            this.id = id;
        }

        @Override
        public void run() {
            currentThread.set(Thread.currentThread());
            // send http request
            String result = service.checkPaymentState(id, bid);
        }

        public void stop() {
            System.out.println("stop!!!");
            currentThread.get().interrupt();
        }
    }

主要方法。如果任务未在2秒内完成,则应将其取消:

Task task = new Task(bid, id);
Future future = taskScheduler.submit(task);

scheduledExecutorService.schedule(() -> {
            if (!future.isDone()) {
                System.out.println("Cancelled!");
                future.cancel(true);
                task.stop();
            }
        }, 2, TimeUnit.SECONDS);

2 个答案:

答案 0 :(得分:3)

从ThreadPool获得的中断线程-不是一个好主意-您不知道线程池中断策略。有一天,您可以将线程池​​的实现更改为不创建新线程的线程池-当某些工作线程被中断并杀死时-最终您将耗尽线程池中的线程。

首选方式是调用future.cancel(true);-在长时间运行的HTTP请求中您将获得InterruptedException

注意:不要捕获InterruptedException并吞下-使其在线程池级别进行处理并应用中断策略。或者吞下它-通过Thread.currentThread().interrupt()

在线程上手动设置中断标志

答案 1 :(得分:0)

您需要按以下方式重写代码:

  1. 提交任务后调用taskScheduler.shutdown()。否则,您的 ExecutorService 将挂起,等待新的 Tasks ,并且不会让 JVM 正常关闭。

  2. 如果希望您的 Thread 在完成后返回值,请实施 Callable

  3. 正如@Oleksandr Papchenko所说:

  

请勿中断从 ThreadPool

获得的 Thread

在您的示例中-不要存储对池的 Thread 的引用,并在您的stop()方法中中断它。您可以按照以下步骤重做run()

public String call() {
         try {
           /*
            * describe logic of your service.checkPaymentState(id, bid) here
            * if you have blocking methods wrap them in a try-catch block
           */
         } catch (InterruptedException e) {
            // Save the interrupted status
            Thread.currentThread().interrupt();
            return null;
         }
         return value;
    }
  1. 删除stop()方法,只需在future.cancel(true)

  2. 中执行scheduledExecutorService
  3. 如果call()中没有阻塞方法,则应制定自己的中断策略。例如,如果使用套接字进行中断,请在外部调用socket.close()并在 SocketException catch子句内部实现中断。