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 inorg.quartz.simplSimpleThreadPool
it simply returns the same value asthreadCount
(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 usingio.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.