简体   繁体   English

为什么我的线程在失败时不超时?

[英]Why aren't my threads timing out when they fail?

So I asked a question a little while ago: Over here that asked the question "How can I make my threads get killed if they take too long" 所以不久前我问了一个问题: 在这里问了一个问题:“如果线程花费的时间太长,我该如何杀死线程”

I have implemented the solution mentioned there but under certain rare circumstances where a thread times out, the program can still fail / lock up (see: Keep the main() method open, and prevent further cron runs of the program). 我已经实现了那里提到的解决方案,但是在某些罕见的情况下,如果线程超时,程序仍然会失败/锁定(请参阅:保持main()方法打开,并防止程序进一步执行cron)。

Here's the source I'm using: 这是我正在使用的来源:

 //Iterate through the array to submit them into individual running threads.
    ExecutorService threadPool = Executors.newFixedThreadPool(12);
    List<Future<?>> taskList = new ArrayList<Future<?>>();
    for (int i = 0; i < objectArray.length; i++) {
        Future<?> task = threadPool.submit(new ThreadHandler(objectArray[i], i));
        taskList.add(task);
        Thread.sleep(500);
    }

    //Event handler to kill any threads that are running for more than 30 seconds (most threads should only need .25 - 1 second to complete.
    for(Future future : taskList){
        try{
            future.get(30, TimeUnit.SECONDS);
        }catch(CancellationException cx){ System.err.println("Cancellation Exception: "); cx.printStackTrace();
        }catch(ExecutionException ex){ System.err.println("Execution Exception: ");ex.printStackTrace();
        }catch(InterruptedException ix){ System.err.println("Interrupted Exception: ");ix.printStackTrace();
        }catch(TimeoutException ex) {future.cancel(true);}
    }
    threadPool.shutdown();
    threadPool.awaitTermination(60, TimeUnit.SECONDS);

So my question is: with this code implemented, why is the executor service not cutting things off at 30 seconds. 所以我的问题是:实施此代码后,为什么执行程序服务不能在30秒后中断工作。

Because I suspect your worker threads are still running. 因为我怀疑您的工作线程仍在运行。 You are calling future.cancel(true); 您正在调用future.cancel(true); but all that does is set the interrupt flag on the thread -- it does not actively interrupt your running code. 但所做的只是在线程上设置中断标志-它不会主动中断正在运行的代码。 Another way to "interrupt" code is to set some volatile boolean shutdown flag to be true and to test for that in your code. “中断”代码的另一种方法是将一些volatile boolean shutdown标志设置为true,然后在代码中进行测试。 See here for more details about interrupting threads . 有关中断线程的更多详细信息,请参见此处。

You need to make sure that your ThreadHandler code handles interrupts correctly. 您需要确保ThreadHandler代码正确处理中断。 It needs to, for example, check Thread.currentThread().isInterrupted() in loops or in other code blocks. 例如,它需要在循环或其他代码块中检查Thread.currentThread().isInterrupted() You also need to make sure that you are handling InterruptedException correctly and not just swallowing the interrupt. 您还需要确保正确处理InterruptedException ,而不仅仅是吞咽中断。

See my answer here for more information about thread interrupts. 有关线程中断的更多信息,请参见此处

You have an increasing amount of timeout for each task which may not be intended. 您可能无法完成的每个任务都有越来越多的超时。 Instead you can shutdown the thread pool after you timeout and cancel the rest. 相反,您可以在超时后关闭线程池并取消其余线程。

threadPool.shutdown();
threadPool.awaitTermination(30, TimeUnit.SECONDS);
threadPool.shutdownNow(); // interrupt any running tasks.

There is a whole chapter dedicated Task Cancellation in the book Java Concurrency in Practice. 《 Java并发实践》一书中有一整章专门介绍了任务取消。 From what I've read the task cancellation has to be in the finally block to make sure the task is always ended. 根据我的阅读,任务取消必须在finally块中,以确保任务总是结束。

    try{
            future.get(30, TimeUnit.SECONDS);

        } catch (TimeoutException e) {
           // log error message and falls through to finally block
        } catch (ExecutionException e) {
            throw e;
        } finally {
            future.cancel(true); // interrupt task
        }

Interrupted status has to be restored while handling the InterruptedException. 处理InterruptedException时必须恢复中断状态。

           catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }

In the ThreadHandler task check Thread.currentThread().isInterrupted() flag and throw an InterruptedException if true propagating the Interrupt status. 在ThreadHandler任务中,检查Thread.currentThread()。isInterrupted()标志并在传播中断状态为true时抛出InterruptedException。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM