处理线程池中Callable抛出的异常

时间:2016-10-19 10:35:34

标签: java spring multithreading

我有一个ThreadPoolTaskExecutor submit CallableExecutor Task个任务Map

Future内,我使用动态Callable来设置一些值。此Callable的{​​{1}}可用于取消此帖子。在开始这个Task之前,我初始化了一些条件,这些条件在线程完成执行时被取消或恢复。

可能存在call尚未启动且已取消的情况。这意味着条件已初始化。但是当一个尚未启动且仍在池中的线​​程被取消时,我无法使我的初始化无效,因为永远不会调用Runnable方法。

我读到了它,如果它是UncaughtExceptionHandler线程,那么我可以使用future.get()来处理它。或者,如果我使用ExecutionException等待结果,那么我可以处理afterExecute()。另一个解决方案是覆盖ThreadPoolTaskExecutor,但我在BlockingQueue中找不到这个,我也不太确定这种方法。

那么在这种情况下如何处理呢?

以下代码是从等待public void process(View view) { //getMapOfViewsAndFuture and getMapOfViewsPersistingLocks fetch the ConcurrentHashMaps viewController.getMapOfViewsAndFuture().remove(view.getId()); viewController.getMapOfViewsPersistingLocks().put(view.getId(), new ReentrantLock()); Callable<WebResponse> calculatePI = (Callable<WebResponse>) mAppContext.getBean("piCalculator", view.getId() ,viewController.getMapOfViewsPersistingLocks().get(view.getId()), viewController.getMapOfViewsPrintingLocks().get(view.getId())); Future<WebResponse> future = mExecutor.submit(calculatePI); viewController.getMapOfViewsAndFuture().put(view.getId(), future); } 的恶魔线程调用的:

class PICalculator implements Callable<WebResponse>
{   
    @Override
    public WebResponse call()
    {
        try
        {
            //business logic
            mWebResponse = getResponse();
        }
        catch(Exception e)
        {
            //log the exceprtion
        }
        finally
        {
            //remove this entry from datasets
            viewController.getMapOfViewsAndFuture().remove(mViewId);
            viewController.getListOfCalculatingViews().remove((Integer)mViewId);
            viewController.getMapOfViewsPersistingLocks().remove(mViewId);
        }

        return mWebResponse;
    }
}

Callable(PICalculator)看起来像这样:

Privacy - LocationWhenInUseUsageDescription

1 个答案:

答案 0 :(得分:0)

很好的问题,使用Spring的ThreadPoolTaskExecutor,您可以为ThreadPoolExecutor(Java内置)提供配置,例如 - corePoolSize, maxPoolSize等,但是您无法设置自定义ThreadPoolExecutor。

在这种情况下,我建议你使用Spring的 ConcurrentTaskExecutor

  1. 使用所需的配置创建Java的ThreadPoolExecutor对象。见下面的构造函数:

     public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue) 
    
  2. 这里你必须提供自己的队列对象。

    1. 现在您可以覆盖afterExecute()方法来清除设置,如下所示:

          ThreadPoolExecutor myExecutor = new ThreadPoolExecutor(3,5,5, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(10)){
      
                  protected void afterExecute(Runnable r, Throwable t) {
                      super.afterExecute(r,t);
                      //Move your cleanup code here
                      //remove this entry from datasets
                     viewController.getMapOfViewsAndFuture().remove(mViewId);
                viewController.getListOfCalculatingViews().remove((Integer)mViewId);
                     viewController.getMapOfViewsPersistingLocks().remove(mViewId);
                      System.out.println("do cleanup here");
                 }
          };
      
    2. 现在在ConcurrentTaskExecutor对象中设置此执行程序。

      ConcurrentTaskExecutor.setConcurrentExecutor(myExecutor);
      

      您甚至可以在ConcurrentTaskExecutor的构造函数中传递执行程序。

        ConcurrentTaskExecutor taskExecutor = new ConcurrentTaskExecutor(myExecutor);   
      
    3. 现在您的taskExecutor已准备好处理您的任务,只需调用submit(callable)方法来传递callables / runnables(任务)。希望它可以帮到你。