目前,我们的一个应用程序中有 2 个线程池:
- 第一个是用于处理计划任务的
- 第二个涉及并行处理正在运行的每个计划任务
需要设置两个不同的池来自以下想法:如果多个计划任务在主(第一个)池中排队,并且它触发同一池中的子任务(并行处理),这将导致竞争条件 as 也会在其他计划任务“后面”排队,因此实际上什么都不会结束,并且会发生死锁。
如果子任务的优先级高于计划任务怎么办?他们会“插队”并暂停计划任务以完成任务吗?或者这不会发生?有什么方法可以强制这种行为吗?或者当 ThreadPoolExecutor 已经在运行任务时,任务无法暂停?
池 1 在 Spring 的应用程序上下文 XML 配置文件中定义为:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:task="http://www.springframework.org/schema/task" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/task
http://www.springframework.org/schema/task/spring-task-3.0.xsd">
<context:annotation-config />
<context:component-scan base-package="cl.waypoint.mailer.reportes" />
<task:annotation-driven scheduler="myScheduler" />
<task:scheduler id="myScheduler" pool-size="2" />
<aop:aspectj-autoproxy />
</beans>
池 2 在代码中定义如下:
public static ThreadPoolExecutor executor = new ThreadPoolExecutor(10, 10, 30, TimeUnit.SECONDS,
new LinkedBlockingDeque<Runnable>(), new ThreadFactory() {
final AtomicLong count = new AtomicLong(0);
private String namePreffix = "TempAndDoor";
@Override
public Thread newThread(Runnable r) {
Thread t = new Thread(r);
t.setDaemon(false);
t.setPriority(Thread.NORM_PRIORITY);
t.setName(MessageFormat.format("{0}-{1}", namePreffix, count.getAndIncrement()));
return t;
}
});
最佳答案
如果我理解正确的话myScheduler(pool1)用于安排任务,一旦时间开始,它就会将任务提交给执行器 (池2)。
给出问题
如果子任务的优先级高于计划任务怎么办?
不清楚如何区分它们或您的真正含义,但我的理解是子任务是计划任务。
我认为你应该有一些类似的代码:
@Scheduled(cron="*/5 * * * * MON-FRI")
public void doSomething() {
executor.submit(aTaskThatRunsInParallelOrWhatYouCallASubTask);
}
其中 executor 是您要在其中创建的静态对象。(不应该全部大写和结尾;))
根据其长名称,您提交给执行器的内容是“子任务”或执行器唤醒提交的任务。在这种情况下,您的 myScheduler 将始终及时唤醒,因为执行的内容是非阻塞的。
另一方面,由于您有一个 LinkedBlockingDeque,这意味着按顺序执行,因此您的执行器可能会得到备份。
另一个问题:
他们会“跳过”队列并暂停计划任务以完成任务吗?
它们不会跳跃,调度程序启动,提交新任务并再次 hibernate 。队列开始变满
下一个问题:
有什么方法可以强制这种行为吗?或者当 ThreadPoolExecutor 已经在运行任务时,任务无法暂停?
您可以一起取消任务,但您将跟踪所有提交的任务
你可以捕获 future
Future aFuture = executor.submit(aTaskThatRunsInParallelOrWhatYouCallASubTask);
不知何故,你需要知道你确实想取消任务,你需要调用
aFuture.cancel();
看起来你需要的东西比较复杂,我建议看看JMS,它非常成熟,或者AKKA可能更容易掌握。
关于java - 处理线程池中的优先级,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40292906/