3

I have quartz-1.8.6/java application that is using default org.quartz.simplSimpleThreadPool with "org.quartz.threadPool.threadCount" (number of worker threads in the pool) set to 20.

I would like to periodically poll for the number of currently available threads in the pool at runtime for diagnostic purpose and if it has been exhausted (current pool size is 0) for some time, log a warning.

How do I access current number of available threads in the pool at runtime?

SimpleThreadPool provides a method getPoolSize(), which, according to javadoc ("Get the current number of threads in the ThreadPool.") is expected to give the information I am looking for. But how do I get a reference to SimpleThreadPool used by quartz scheduler?

I initialize my quartz scheduler as follows:

SchedulerFactory schedFact = new StdSchedulerFactory();
System.setProperty(StdSchedulerFactory.PROP_SCHED_INSTANCE_NAME,
    this.defaultThreadName);
System.setProperty("org.quartz.threadPool.threadCount",
    ""+this.threadPoolSize);
scheduler = schedFact.getScheduler();

I am thinking to add global listener as follows:

scheduler.addGlobalJobListener(new JobListener() {
    public void jobToBeExecuted(JobExecutionContext context) {
        Scheduler s = context.getScheduler();

        // How to get reference to thread pool from scheduler?
        // --> ...
    }
    // other JobListener interface methods 
    // ...
});

I don't see any methods in the Scheduler to access threadPool instance or poolSize property directly. Is there a way to do that?

ANSWER: After a few trials I found the answer to my own question that I would like to share:

  • As I mentioned in the comments below getPoolSize() actually does not work for me since as implemented in org.quartz.simplSimpleThreadPool it simply returns the same value as threadCount (the number of worker threads in the pool), which will always be the same:
    public int getPoolSize() {
        return getThreadCount();
    }

    /**
     * <p>
     * Set the number of worker threads in the pool - has no effect after
     * <code>initialize()</code> has been called.
     * </p>
     */
    public void setThreadCount(int count) {
        this.count = count;
    }

  • The method that does the job for me is QuartzScheduler.getCurrentlyExecutingJobs(). The size of the returned list is exactly what I need. For the quick proof of concept I added the following global listener to the scheduler to log the currently used number of threads (NOTE: I am using io.vavr.control.Try in the sample code, for more info please refer to https://www.vavr.io/vavr-docs/#_try):
scheduler.addGlobalJobListener(new JobListener() {
    @Override
    public void jobToBeExecuted(JobExecutionContext context) {
        Scheduler s = context.getScheduler();
        JobDetail jd = context.getJobDetail();
        // cast raw generic List to List<?> for stream() to work
        Try<List<?>> tryGetCurrentJobs = Try.of(() -> s.getCurrentlyExecutingJobs());
        tryGetCurrentJobs
        .onSuccess(jobs -> {
            List<JobExecutionContext> currentJobs = jobs.stream()
                .map(o -> (JobExecutionContext)o) // any type error will be discovered here
                .collect(Collectors.toList());
            logger.info(format(
                "job to be executed [%s:%s] - quartz scheduler is using %d out of %d threads in the pool.",
                jd.getGroup(), jd.getName(), currentJobs.size(), threadPoolSize));
            });
    }
    // other JobListener interface methods 
    // ...
});

  • For the final solution I opted to implement a singleton watcher that runs a single thread with scheduled thread pool executor (outside of quartz scheduler). The watcher will hold the reference to the quartz scheduler and will collect pool usage information for the specified interval of time, analyse it and send notification if pool usage exceeds a pre-defined threshold.
dzakharov
  • 332
  • 4
  • 8
  • I can see there is a method to get hold of threadPoolSize in QuartzScheduler class which is concrete implementation of scheduler.You need to get hook to that instance. – user06062019 Sep 13 '19 at 15:50
  • Thank you, @user06062019. I thought threadPoolSize would work for me but as implemented in org.quartz.simpl.SimpleThreadPool it just returns thread count, which is just the maximum number of worker threads in the pool. So this value will always be the same. The method that works for me is QuartzScheduler.getCurrentlyExecutingJobs() and the size of the returned list is exactly what I need. – dzakharov Sep 17 '19 at 14:32

0 Answers0