java 调度程序 Spring 与 Quartz

标签 java spring scheduler

目前我正在构建一个 Spring 独立程序,以学习新的方法和架构。
最近几天我尝试学习调度程序。我以前从未使用过它们,所以我阅读了一些处理不同可能方法的文章。其中两个特别有趣:spring nativ @Scheduler 和 Quartz。

据我所知,Spring 比 Quartz 小一点,而且更加基础。而且 quartz 不太容易与 Spring 一起使用(因为自动接线和组件)。

我现在的问题是,有一件事我不明白:
根据我的理解,这两种方法都创建并行线程以便异步运行作业。但是,如果我现在在我的主应用程序中有一个 spring @Service,它持有一个包含一些信息的 HashMap,该怎么办?数据随着用户交互而更新和改变。并行还有调度程序。调度程序现在也想在主应用程序中使用这个 HashMap。这可能吗?
还是我理解有问题?因为还有@Async注解,我不明白其中的区别。因为调度程序本身已经与主语料库并行了,不是吗?

(总结一下,两个问题:

  • 每五秒执行一次、使用调度程序实现的作业是否可以在主程序内的服务之外使用 HashMap? (在 spring @Scheduler 和/或 Quartz 中?)
  • 为什么要有@Async注解。调度程序不是已经与主进程并行了吗?

)

最佳答案

我必须对您正在使用的 Spring 版本做出一些假设,但是当您处于学习过程中时,我会假设您正在使用 spring-boot 或相当新的版本,所以请原谅如果注释与您的 Spring 版本不匹配。这就是说,我能尽力回答你的两个问题:

can a job that is executed every five seconds, implemented with a scheduler, use a HashMap out of a service inside the main program? (in spring @Scheduler and/or in Quartz?)

是的,绝对!最简单的方法是确保所讨论的 HashMap 被声明为静态的。要从计划作业访问 HashMap ,只需 Autowiring 服务类或为 HashMap 创建静态获取函数即可。

这是最近 Vaadin 项目的示例,我需要向一组订阅者发送预定消息。

SchedulerConfig.class

@Configuration
@EnableAsync
@EnableScheduling
public class SchedulerConfig {

    @Scheduled(fixedDelay=5000)
    public void refreshVaadinUIs() {
        Broadcaster.broadcast( 
                new BroadcastMessage(
                    BroadcastMessageType.AUTO_REFRESH_LIST 
                ) 
        );
    }

}

广播者.class

public class Broadcaster implements Serializable {

    private static final long serialVersionUID = 3540459607283346649L;

    private static ExecutorService executorService = Executors.newSingleThreadExecutor();

    private static LinkedList<BroadcastListener> listeners = new LinkedList<BroadcastListener>();

    public interface BroadcastListener {
        void receiveBroadcast(BroadcastMessage message);
    }   

    public static synchronized void register(BroadcastListener listener) {
        listeners.add(listener);
    }

    public static synchronized void unregister(BroadcastListener listener) {
        listeners.remove(listener);
    }

    public static synchronized void broadcast(final BroadcastMessage message) {
        for (final BroadcastListener listener: listeners)
            executorService.execute(new Runnable() {
                @Override
                public void run() {
                    listener.receiveBroadcast(message);
                }
            });
    }
}

Why is there a @Async annotation. Isn't a scheduler already parallel to the main process?

是的,调度程序在自己的线程中运行,但是调度程序在长时间运行的任务上会发生什么情况(即:对远程服务器进行 SOAP 调用需要很长时间才能完成)?

调度不需要 @Async 注释,但如果调度程序调用一个长时间运行的函数,它就变得非常重要。

这个注解用于获取一个特定的任务并请求Spring的TaskExecutor在它自己的线程而不是当前线程上执行它。 @Async 注释使函数立即返回,但稍后将由 TaskExecutor 执行。

这就是说,如果没有 @EnableAsync 或 @Async 注释,您调用的函数将占用 TaskScheduler,因为它们将在同一线程上执行。在长时间运行的操作中,这将导致调度程序被挂起,并且在返回之前无法执行任何其他调度函数。

我建议阅读Spring's Documentation about Task Execution and Scheduling它对 Spring 中的 TaskScheduler 和 TaskExecutor 提供了很好的解释

关于java 调度程序 Spring 与 Quartz,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39520868/

相关文章:

go - 为什么我们在 Go 调度器的设计中添加 P 而不是简单地更改 M?

java - 使用 Java 8 将接口(interface)类型列表转换为另一个类的列表

java - Android Gradle 异常 : "Multiple dex files define", exploded-aar 下的重复类

java - Java自动删除JSON字符串中的引号

servlet spring 的 javax.servlet.ServletException : Servlet. init() 抛出异常

hibernate - LazyInitializationException 即使 openSessionInViewInterceptor

java - @ConditionalOnBean 不适用于手动注册的 bean

java - 如何在一段时间后重复运行线程

java - URL参数编码/接收问题

java - 如何实现/模拟作业调度程序?