处理悬挂任务

时间:2016-02-09 09:00:37

标签: java multithreading

这只是解释我的问题的一个例子......

我正在使用带有20个活动线程和75K最大排队项目的ExecutorService ...

在我的情况下,正常任务不应超过10秒,如果花费更多时间意味着任务有问题。

如果由于有问题的任务导致所有线程都挂起,我的RejectionHandler将重启整个服务。

我在这里有两个问题:

  
      
  1. 我不喜欢重启服务的想法,相反,如果有的话   检测挂起线程的方法,我们可以重新启动挂起   线程会很棒。我已经阅读了几篇文章来处理使用ThreadManager挂起的线程,但是没有找到任何东西   使用ExecutorService。

  2.   
  3. 我对Executors.newCachedThredPool()非常着迷   因为在高峰期,我们负担过重的任务,并且   在其他日子里,他们很少。任何建议都会很大   赞赏。

  4.   
   public class HangingThreadTest {

    // ExecutorService executorService = Executors.newCachedThreadPool()
    private static ExecutorService  executorService = new ThreadPoolExecutor(10,
            20, 5L, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>(75000));

    public static void main(String... arg0) {
        for (int i = 0; i < 50000; i++) {

            executorService.submit(new Task());
        }
    }

}

/**
 * Task to be completed
 */
class Task implements Runnable {

    private static int count = 0;

    @Override
    public void run() {

        count++;
        if (count%5 == 0) {
            try {
                System.out.println("Hanging Thread task that needs to be reprocessed: "
                        + Thread.currentThread().getName()+" count: "+count);
                Thread.sleep(11000);
            } catch (InterruptedException e) {
                // Do something
            }
        }
        else{
            System.out.println("Normal Thread: "
                    + Thread.currentThread().getName()+" count: "+count);
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                //Do something
            }
        }

    }

}

2 个答案:

答案 0 :(得分:2)

Executors框架中没有内置机制可以帮助终止一个线程,如果它已经运行超过一个阈值。

但我们可以通过以下一些额外代码来实现这一目标:

  1. 获取executorService.submit(...);返回的Future对象。
  2. Future future = executorService.submit(new Task());

    1. 调用此future对象上的get方法,并使其等待任务完成的阈值间隔。下面是一个等待仅2秒的例子。

      try {
              f.get(2, TimeUnit.SECONDS);
          } catch (TimeoutException e) {
              f.cancel(true);
          } catch (Exception e) {}
      
    2. 上面的代码等待2秒完成任务,如果在此期间没有完成,它会抛出TimeoutException。随后我们可以在未来对象上调用cancel方法。这导致在执行任务的线程中设置interrupt标志。

      1. 现在最后的更改是,在Task类代码中我们需要检查必要的点(取决于应用程序),interrupt标志是否已使用isInterrupted()方法设置为true Thread类。如果中断== true,我们可以立即进行必要的清理并从run方法返回。这里的关键部分是确定Task类中您要检查此中断标志的必要点。
      2. 这使线程可用于处理下一个任务。

答案 1 :(得分:0)

您可能会看一下这篇文章,在我遇到同样的问题之前对我非常有帮助:Java Hanging Thread Detection