Spring TaskExecutor无限队列

时间:2018-06-04 06:33:06

标签: java spring queue executor

我实现了Spring-TaskExecutor(它相当于JDK 1.5的执行程序。)来处理从外部系统接收的通知通知。

仅使用一种方法进行接口:

public class AsynchronousServiceImpl implements AsynchronousService {

    private TaskExecutor taskExecutor;

    @Override
    public void executeAsynchronously(Runnable task) {
        taskExecutor.execute(task);
    }

    @Required
    public void setTaskExecutor(TaskExecutor taskExecutor) {
        this.taskExecutor = taskExecutor;
    }
}

和相应的实现:

<bean id="taskExecutor" class="org.example.impl.NotificationPool">
        <property name="corePoolSize" value="1"/>
        <property name="maxPoolSize" value="1"/>
        <!--<property name="queueCapacity" value="100"/>-->
        <property name="WaitForTasksToCompleteOnShutdown" value="true"/>
</bean>

任务执行程序(遗留应用程序)的Xml配置:

public class NotificationPool extends ThreadPoolTaskExecutor {
     @Override
     protected BlockingQueue<Runnable> createQueue(int queueCapacity) {
          return new PriorityBlockingQueue<>(queueCapacity);
        }
    }
因为我希望任务顺序执行(只有1个线程由处理任务的池创建),所以

1同时为corePoolSize和maxPoolSize设置。

我想根据收到通知的日期订购我的任务,我需要覆盖此功能以允许优先顺序:

public class NotificationTask implements Runnable, Comparable<NotificationTask> {

    private final NotificationService notificationService;
    private final Notification notification;

    public NotificationService(NotificationService notificationService, 
                               Notification notification) {
        this.notificationService = notificationService;
        this.notification = notification;
    }

    @Override
    public int compareTo(NotificationTask task) {
        return notification.getTimestamp().compareTo(task.getTimestamp());
    }

    @Override
    public void run() {
        notificationService.processNotification(notification);
    }
}

以下是通知任务类:

asynchronousService.executeAsynchronously(new NotificationTask (notificationService, notification));

这就是我执行它的方式:

<!--<property name="queueCapacity" value="100"/>-->

这适用于有界队列,但我需要一个无界的队列。 正如您在xml-configuration上看到的那样,用于定义队列容量的行已被注释掉:

{{1}}

但是,如果我这样做,那么我会得到一个OutOfMemoryException。它似乎试图在应用程序的开头创建一个无界队列。但是,Executor-Service允许我们使用无界排队 - 但我不知道如何在这里做到这一点。

1 个答案:

答案 0 :(得分:1)

根据java doc:

  

一个无限制的阻塞队列,它使用与类PriorityQueue相同的排序规则,并提供阻塞检索操作。虽然此队列在逻辑上是无限制的,但由于资源耗尽(导致OutOfMemoryError),尝试添加可能会失败

基本上,它是无限的,你不需要关心队列大小。

但是,队列由数组支持:

public PriorityBlockingQueue(int initialCapacity,
                             Comparator<? super E> comparator) {
    if (initialCapacity < 1)
        throw new IllegalArgumentException();
    this.lock = new ReentrantLock();
    this.notEmpty = lock.newCondition();
    this.comparator = comparator;
    // Here is the initialization of backed array
    this.queue = new Object[initialCapacity];
}

因此您需要提供合理的初始队列大小。在那之后,你已经完成了。

但是,如上所述,随着越来越多的元素出现,如果内部数组已满,当队列尝试增长内部数组时,队列可能会抛出OutOfMemory异常。

private void tryGrow(Object[] array, int oldCap)

但这是不太可能的,除非你的项目在短时间内产生数百万的通知