在ThreadPools

时间:2016-10-27 19:37:23

标签: java multithreading threadpool priority-queue thread-priority

目前,我们的某个应用中有2个线程池:

  1. 第一个是用于处理预定任务的那个
  2. 第二个处理正在运行的每个计划任务的并行处理
  3. 需要设置两个不同的池来自以下思路:如果几个计划任务在主(第一)池中排队,并且它在同一池中触发它的子任务(并行处理),这将导致一场比赛条件也将排在其他计划任务的“后面”,所以什么都不会实际结束并发生死锁。

    如果子任务的优先级高于计划任务,该怎么办?他们会“跳”队列并暂停计划任务以完成吗?或者那不会发生?有没有办法强迫这种行为?或者当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;
                }
            });
    

1 个答案:

答案 0 :(得分:2)

如果我理解正确 myScheduler (pool1)用于安排任务,一旦启动任务,就会将任务提交给 executor (pool2)。

给出问题

如果子任务的优先级高于计划任务,该怎么办?

不清楚你如何区分它们或你真正的意思,但我理解的是子任务是计划任务。

我认为你应该有一些代码:

@Scheduled(cron="*/5 * * * * MON-FRI")
public void doSomething() {
    executor.submit(aTaskThatRunsInParallelOrWhatYouCallASubTask);
}

其中executor是你创建的静态对象。(不应该是全部大写和最终的;)

根据其长名称,您向执行人提交的内容是“子任务”或执行者唤醒提交的任务。在这种情况下,你的myScheduler会及时唤醒,因为执行的是非阻塞的。

另一方面,由于您有一个LinkedBlockingDeque,这意味着按顺序执行,您的 执行程序 可能会被备份。

另一个问题:

他们会“跳”队列并暂停计划任务以完成吗?

他们不会跳,调度员开始,提交新任务并再次休眠。队列开始填满

下一个问题:

有没有办法强迫这种行为?或者当ThreadPoolExecutor已经运行它们时,无法暂停任务?

你可以一起取消任务,但是你将跟踪所有提交的任务

你可以抓住未来

Future aFuture = executor.submit(aTaskThatRunsInParallelOrWhatYouCallASubTask);

以某种方式你需要知道你真的要取消任务,你需要调用

aFuture.cancel();

看起来你需要的是更多参与,我建议看看非常成熟的JMS或可能更容易掌握的AKKA。