我实现了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允许我们使用无界排队 - 但我不知道如何在这里做到这一点。
答案 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)
但这是不太可能的,除非你的项目在短时间内产生数百万的通知