代码之家  ›  专栏  ›  技术社区  ›  Sarvar Nishonboyev

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

  •  0
  • Sarvar Nishonboyev  · 技术社区  · 6 年前

    我有下面的任务类,它向API发送http请求。如果进程花费的时间太长,我想通过调用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 回复  |  直到 6 年前
        1
  •  3
  •   Oleksandr Papchenko    6 年前

    中断线程是从线程池得到的-是个坏主意-你不知道线程池 中断策略 . 有一天,您可以将线程池的实现更改为不创建新线程的实现—当一些工作线程被中断和终止时—最终您将用完线程池中的线程。

    首选的方法是打电话 future.cancel(true); -你会得到 InterruptedException -在长时间运行的HTTP请求上。

    注意:不要接住 中断异常 和swallow—让它在线程池级别上处理,并应用中断策略。或者如果吞下它-在线程上手动设置中断标志 Thread.currentThread().interrupt()

        2
  •  0
  •   Nick    6 年前

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

    1. 援引 taskScheduler.shutdown() 提交任务之后。否则你的 执行者服务 将等待新的 任务 而且不会让 虚拟机 优雅地关机。

    2. 如果你想 线程 在完成实现后返回值 可赎回的 相反

    3. 正如@Oleksandr Papchenko所说:

    不要打断 线程 那是从 线程池

    在您的示例中-不要存储对池的 线程 打断你的谈话 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. 删除 停止() 方法和简单的做 future.cancel(true) scheduledExecutorService

    2. 如果里面没有阻塞方法 call() 你应该详细说明你自己的中断政策。例如,如果使用套接字进行中断调用 socket.close() 外部和内部中断 套接字异常 catch子句。