在ThreadPoolExecutor中使用LinkedBlockingQueue(Integer.MAX_VALUE)时发生RejectedExecutionException

时间:2019-03-28 10:47:23

标签: exception concurrency java-8 websphere blockingqueue

我将ThreadPoolExecutor与LinkedBlockingQueue(Integer.MAX_VALUE)一起用于多个任务,但是为什么在Websphere的2000个任务中提交(可调用任务)时却抛出RejectedExecutionException?从理论上讲队列不应该能够包含21亿个任务吗?任何信息将不胜感激。

发送到我的应用程序的两个soap请求将执行两个不同的作业,这两个作业中的每个作业均由一个作业类处理,并且将实例化一个自定义的ServiceExecutionFactory(带有原型的bean),充当消费者和生产者工厂。工厂有一个workQueue(size 1000)字段来包含作业类生成的任务,使用者将在workQueue中取出任务并将其放入线程池。顺便说一句,我不能用Tomcat复制它。

实例ThreadPoolExecutor

BlockingQueue<Runnable> executorQueue = new LinkedBlockingQueue<Runnable>();
ThreadPoolExecutor tpe = (new ThreadPoolExecutor(poolSize, poolSize, 10, TimeUnit.SECONDS, executorQueue, tf));
tpe.allowCoreThreadTimeOut(true);

executorService.submit(serviceInfo.getCallable())可能会抛出RejectedExecutionException,因为所有线程都被占用(包括外部线程),并且队列已满(我不知道为什么会发生上述情况)。然后,程序将捕获该异常并尝试将其添加回队列中,此时ServiceExecutionFactoryBase的workQueue(大小1000)可能已满,无法添加,它将使用add()抛出队列已满的异常方法。我还感到奇怪的是,ConsumerService将在3小时后重新工作,但是此ConsumerService线程应该由于throw e语句而停止,不是吗?

public class ConsumerService implements Callable<Object> {

       public Object call() throws Exception {

           // loop until interrupted
           try {
               while (true) {

                   // check the work queue for available item
                   ServiceInfo serviceInfo = queue.take();
                   // When an item is available, feed it to the executor, and save the future
                   try {
                       Future<Object> future = executorService.submit(serviceInfo.getCallable());
                       serviceInfo.setFuture(future);
                       serviceInfo.setCallable(null);
                   } catch (Exception e) {
                       if (serviceInfo.getRetrys() < getMaximumRequestRetries()) {
                           serviceInfo.setRetrys(serviceInfo.getRetrys() + 1);
                           queue.add(serviceInfo);
                       } else {
                           ServiceCaller sc = serviceInfo.getCallable();
                           sc.factory.notifyServiceAborted(sc.serviceKey, e);
                       }
                   }
               }
           } catch (InterruptedException e) {
               // the job is done
               return null;
           } catch (Exception e) {
               getLogger().error(e);
               throw e;
           }
       }

   }

我希望没有RejectExecutionException发生,但是会发生。

1 个答案:

答案 0 :(得分:0)

您正在使用的类java.util.concurrent.ThreadPoolExecutorjava.util.concurrent.LinkedBlockingQueue由JDK提供,与您使用的应用程序服务器无关。两种情况下都使用相同的JDK吗?如果是这样,另一个可能的原因可能是其中一种环境中的内存消耗较高,使得ThreadPoolExecutor无法分配新线程,并在此基础上拒绝submit请求。即使您将corePoolSize设置为与maximumPoolSize相同,您还同时设置了allowCoreThreadTimeOut,从而有可能减少线程数并要求创建新线程。