【问题标题】:Which is the recommended way as a client to get handle to the scheduler?作为客户端处理调度程序的推荐方式是什么?
【发布时间】:2013-12-09 13:23:22
【问题描述】:

我正在使用 Quartz Scheduler v1.8.3 并集成到 Apache Tomcat v6.0.10 中,因此调度程序是 initialized from within servlet container。作业也从 Apache Tomcat 中添加/调度到调度程序。

我正在设计一个 JSP Web 前端页面 (quartzAdmin.jsp),我只想查看调度程序信息,如 meta-data 值、所有作业详细信息及其触发器、当前正在执行的作业等。

我的问题是,为了获得调度程序的句柄,建议使用以下 2 个选项之一:

方案一:直接调用schedulerFactory.getScheduler()获取句柄

SchedulerFactory sf = new StdSchedulerFactory();
Scheduler scheduler = sf.getScheduler();

选项 2:通过实现单例模式获取句柄

public class Quartz {

    private Quartz() {
    }

    private static Scheduler scheduler = null;

    public static Scheduler getScheduler() {
        if(scheduler == null) {
            SchedulerFactory sf = new StdSchedulerFactory();
            scheduler = sf.getScheduler();
        }
        return scheduler;
    }
}

然后在我的quartzAdmin.jsp 中,只需调用Quartz.getScheduler() 就会返回调度程序的句柄。

【问题讨论】:

标签: java singleton quartz-scheduler


【解决方案1】:

我认为这两个选项的作用是创建一个 new 调度程序,而不是获取您在 web.xml 中配置的调度程序。

目前我正在这样做(类似于选项 1):

...为我的 webapp 配置一个 QuartzInitializerListener ... // 我的 servlet 的 init() 公共无效初始化(ServletConfig 配置)抛出 ServletException { ... SchedulerFactory 工厂 = (SchedulerFactory) config.getServletContext().getAttribute( QuartzInitializerListener.QUARTZ_FACTORY_KEY ); 调度器 factory.getScheduler(); ... }

【讨论】:

  • 不,我正在获取之前从web.xml 初始化的调度程序的句柄。我可以使用scheduler.getMetaData().getSummary() 验证这一点并检查这一行Running since: xxxxx
  • 我相信这已经被 Quartz 调度器自己处理好了。
  • 好吧,那么就没有必要使用单例了,因为 Quartz 正在处理这个问题。只需使用选项 1。
【解决方案2】:

你在这里描述的是一个单例模式,你的单例初始化不是线程安全的。

我建议不要在这里使用单例,而是将Quartz 的引用添加到ServletContext,可能在ServletContextListener 中对其进行初始化。

web.xml

<listener>
  <listener-class>my.package.MyServletContextListener</listener-class>
</listener>

MyServletContextListener.java

package my.package;

public class MyServletContextListener implements ServletContextListener
{
    @Override
    public final void contextInitialized (
            final ServletContextEvent event
        )
    {
        final ServletContext servlet_ctx = event.getServletContext( );

        Quartz quartz = new Quartz( );

        servlet_ctx.addAttribute( Quartz.ATTRIBUTE_NAME, quartz );
    }

    @Override
    public void contextDestroyed (
            final ServletContextEvent event
        )
    {
        final ServletContext servlet_ctx = event.getServletContext( );

        Quartz.fromContext( servlet_ctx ).shutdown( );

        servlet_ctx.removeAttribute( Quartz.ATTRIBUTE_NAME );
    }
}

Quartz.java

public final static String ATTRIBUTE_NAME = Quartz.class.getName( );

public Quartz( )
{
    ...
}

public static Quartz fromContext( final ServletContext ctx )
{
  return ctx.getAttribute( ATTRIBUTE_NAME );
}

public void shutdown( )
{
    ...
}

【讨论】:

  • 假设除了获取与调度程序相关的信息外,我不使用调度程序进行任何操作,是否仍应使其成为线程安全的?希望您在这种情况下的意思是“不是线程安全的”,对吗?另外,我无法清楚地理解您提到的建议。你能用一些简单的代码示例解释一下吗?
  • @Gnanam。如果您打算直接从 JSP 调用原始 getScheduler() 方法(不推荐),它肯定会从多个线程调用。检查这篇文章以获得初始化单例的正确方法:stackoverflow.com/questions/3635396/…
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-08-26
  • 1970-01-01
  • 2014-04-30
  • 2018-06-12
  • 2015-07-01
相关资源
最近更新 更多