目前我正在建立一个独立的弹簧程序,以学习新的方法和架构 最近几天我试着学习调度程序。我之前从未使用它们,因此我阅读了一些处理不同方法的文章。其中两个特别有趣:春天nativ @Scheduler和Quartz。
从我读到的内容来看,Spring比Quartz小一点,而且更基本。石英不易与弹簧一起使用(因为自动装配和组件)。
我现在的问题是,有一件事我不明白:
根据我的理解,这两种方法都是创建并行线程,以便异步运行作业。但是如果我现在在我的主应用程序中有一个spring @Service,那就是拿着一些带有一些信息的HashMap。通过用户交互更新和更改数据。并行有调度程序。并且调度程序现在也想要从主应用程序中使用此HashMap。这有可能吗?
或者我理解错了什么?因为还有@Async注释,我不明白其中的区别。因为调度程序本身已经与主语料库平行,所以不是吗?
(总结,两个问题:
)
答案 0 :(得分:3)
我必须对你正在使用哪个版本的Spring做一些假设,但是当你在学习的过程中,我会假设你正在使用spring-boot或者公平新版本,请原谅,如果注释与您的Spring版本不符。这就是说,尽我所能回答你的两个问题:
使用调度程序实现的每五秒执行一次的作业是否可以在主程序中使用HashMap? (在春天@Scheduler和/或Quartz?)
是的,绝对!最简单的方法是确保将有问题的hashmap声明为static。要从计划作业访问hashmap,只需要自动装配服务类或为hashmap创建静态get函数。
以下是最近Vaadin项目的示例,其中我需要向一组订阅者发送预定消息。
<强> SchedulerConfig.class 强>
@Configuration
@EnableAsync
@EnableScheduling
public class SchedulerConfig {
@Scheduled(fixedDelay=5000)
public void refreshVaadinUIs() {
Broadcaster.broadcast(
new BroadcastMessage(
BroadcastMessageType.AUTO_REFRESH_LIST
)
);
}
}
<强> Broadcaster.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);
}
});
}
}
为什么会有@Async注释。是不是已经与主流程并行的调度程序?
是的,调度程序在其自己的线程中运行,但调度程序在长时间运行的任务中会发生什么(即:对需要很长时间才能完成的远程服务器进行SOAP调用)?
调度不需要@Async注释,但如果调度程序调用了长时间运行的函数,则它变得非常重要。
此注释用于执行特定任务并请求Spring的TaskExecutor在其自己的线程而不是当前线程上执行它。 @Async注释使函数立即返回,但稍后将由TaskExecutor执行。
这就是说,如果没有@EnableAsync或@Async注释,你调用的函数将占用TaskScheduler,因为它们将在同一个线程上执行。在长时间运行的操作中,这将导致调度程序被挂起,并且在返回之前无法执行任何其他计划的函数。
我建议阅读Spring's Documentation about Task Execution and Scheduling它提供了Spring中TaskScheduler和TaskExecutor的一个很好的解释