Wait in Main Thread for Quartz Scheduler to Finish - java

I have a Java application that makes use of a Quartz Scheduler in the guise of a SchedulerFactoryBean. The main() method gets the application context, retrieves the root bean, and commences scheduling jobs.
The issue is that the Scheduler runs in its own thread, so when the main thread is done submitting jobs, it returns and the Scheduler goes on without it. When the Scheduler is finally done (or even if you explicitly call shutdown() on it), the application just hangs there for all eternity.
I have two solutions:
Keep track of the job/trigger count, incrementing it whenever you add a job to the Scheduler. Attach a simple SchedulerListener to the Scheduler that decrements this count with every call to triggerFinalized(), and set up a while loop with a Thread.sleep() inside it that constantly checks to see if the count has hit 0. When it does, it will return up to the main() method and the application will exit normally.
Take the custom SchedulerListener from option 1, and keep track of the job count inside of it. Increment for every call to jobAdded(), and decrement for every call to triggerFinalized(). When the count hits 0, call shutdown() on the Scheduler (or not, it doesn't actually matter) and then call System.exit(0).
I have implemented both of these independently in turn, so I know they both actually function. The problem is that they are both terrible. An infinite while loop polling a value? System.exit(0)? Bleargh.
Does someone have a better way, or are these seriously my only options here?
Edit: While thinking about this on the way home, I came to the conclusion that this may be caused by the fact that I'm using SchedulerFactoryBean. This auto-starts when Spring initializes the application context - that seems to put it outside the scope of the main thread. If I went with a slightly different Scheduler that I manually initialized and called start() on in the code, would this run the Scheduler in the main thread, thus blocking it until the Scheduler completes running all jobs? Or would I still have this problem?
Edit: Son of a...http://quartz-scheduler.org/documentation/quartz-2.x/examples/Example1
To let the program have an opportunity to run the job, we then sleep for 90 seconds. The scheduler is running in the background and should fire off the job during those 90 seconds.
Apparently, that will not work, because the scheduler seems to always run in the background.

In your SchedulerListener add an object solely for synchronization and locking. Call it exitLock or something. You main thread retrieves the scheduler, sets up the listener, submits all the jobs and then just before returning executes
Object exitLock = listener.getExitLock();
synchronized (exitLock) {
exitLock.wait(); // wait unless notified to terminate
}
On every triggerFinalized() call your listener decrements the counter for pending jobs. Once all the jobs have finished executing your listener shuts the scheduler down.
if (--pendingJobs == 0)
scheduler.shutdown(); // notice, we don't notify exit from here
Once the scheduler shuts down it invokes one last callback on the listener where we notify the main thread to terminate and hence the program exits gracefully.
void schedulerShutdown() {
// scheduler has stopped
synchronized (exitLock) {
exitLock.notify(); // notify the main thread to terminate
}
}
The reason we didn't notify in triggerFinalized() when all the pending jobs were finished is that in case the scheduler was shutdown prematurely and not all the jobs were finished we would have left our main thread hanging. By notifying in response to the shutdown event we make sure our program exits successfully.

I think here can be another solution.
Key points:
When task was executed the last time context.getNextFireTime() returns null.
Scheduler.getCurrentlyExecutingJobs == 1 indicate that it is the last executed job.
So when point 1 and 2 is true we can shutdown Scheduler and call System.exit(0).
Here is the code:
Listener
public class ShutDownListenet implements JobListener {
#Override
public String getName () { return "someName"; }
#Override
public void jobToBeExecuted (JobExecutionContext context) {}
#Override
public void jobExecutionVetoed (JobExecutionContext context) {}
#Override
public void jobWasExecuted (JobExecutionContext context, JobExecutionException jobException) {
try {
if (context.getNextFireTime() == null && context.getScheduler().getCurrentlyExecutingJobs().size() == 1) {
context.getScheduler().shutdown();
System.exit(0);
}
} catch (SchedulerException e) {
e.printStackTrace();
}
}
}
Code in the main function
public static void main (String[] args) {
Trigger trigger = ...
Job job = ...
JobListener listener = new ShutDownListenet();
scheduler.getListenerManager().addJobListener(listener);
scheduler.scheduleJob(job, trigger);
}
NOTE
I do not write synchronized blocks, but I tested this code with 100 concurent jobs, it works.
Did not tested in "complex" enviroment: clusters or RMI. (behavior can be differ).
Any comments are wellcome.

If your Quartz schedules/triggers are based on the database then you program needs to be alive till you would want to stop it. This can be doable like below. The idea is hook SchedulerListener and wait in the main thread. You need to hook your own way to terminate the program gracefully which completely a different topic itself.
public static void main(String[] args) {
AnnotationConfigApplicationContext appContext = // initialize the your spring app Context
// register the shutdown hook for JVM
appContext.registerShutdownHook();
SchedulerFactoryBean schedulerFactory = appContext.getBean(SchedulerFactoryBean.class);
scheduler = schedulerFactory.getScheduler();
final Lock lock = new ReentrantLock();
final Condition waitCond = lock.newCondition();
try {
scheduler.getListenerManager().addSchedulerListener(new SchedulerListener() {
#Override
public void jobAdded(JobDetail arg0) {
}
#Override
public void jobDeleted(JobKey arg0) {
}
#Override
public void jobPaused(JobKey arg0) {
}
#Override
public void jobResumed(JobKey arg0) {
}
#Override
public void jobScheduled(Trigger arg0) {
}
#Override
public void jobUnscheduled(TriggerKey arg0) {
}
#Override
public void jobsPaused(String arg0) {
}
#Override
public void jobsResumed(String arg0) {
}
#Override
public void schedulerError(String arg0, SchedulerException arg1) {
}
#Override
public void schedulerInStandbyMode() {
}
#Override
public void schedulerShutdown() {
lock.lock();
try {
waitCond.signal();
}
finally {
lock.unlock();
}
}
#Override
public void schedulerShuttingdown() {
}
#Override
public void schedulerStarted() {
}
#Override
public void schedulerStarting() {
}
#Override
public void schedulingDataCleared() {
}
#Override
public void triggerFinalized(Trigger arg0) {
}
#Override
public void triggerPaused(TriggerKey arg0) {
}
#Override
public void triggerResumed(TriggerKey arg0) {
}
#Override
public void triggersPaused(String arg0) {
}
#Override
public void triggersResumed(String arg0) {
}
});
// start the scheduler. I set the SchedulerFactoryBean.setAutoStartup(false)
scheduler.start();
lock.lock();
try {
waitCond.await();
}
finally {
lock.unlock();
}
} finally {
scheduler.shutdown(true);
}
}

If it helps someone else. I solved this by adding a shutdown-hook that triggers on Ctrl-C or normal kill (15) from script. A new Thread is spawned and polls the getCurrentlyExecutingJobs().size() every 3 seconds and exits when jobs counter has reached zero meaning all jobs finished.
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
try {
while (jobScheduler.getScheduler().getCurrentlyExecutingJobs().size() > 0) {
Thread.sleep(3000);
}
jobScheduler.getScheduler().clear();
} catch (Exception e) {
e.printStackTrace();
}
}));

while (!scheduler.isShutdown())
{
Thread.sleep(2L * 1000L);//Choose reasonable sleep time
}

Related

Use ScheduledExecutorService schedule to schedule a task from a spawned thread?

I am planning on implementing a timer service for my java application.
The core structure is like so.
In the Base class, I call scheduleATassk() to start the first task with delay set. When the delay is up, it will call onTimeUp() to notify me that we can calculate the next alarm duration. So in onTimeUp(), if the conditions are met, i will call scheduleATassk() with the new duration and the cycles repeats.
My question is:
The very first task will be scheduled by the main thread (notice in the Base class's constructor (the main thread), it calls scheduleATassk() to get the alarm running). However, any subsequent scheduleATassk() will be call by the child thread. Are there any effect? Is it safe? Can I improve on the design?
public class Base {
private ScheduledExecutorService service = null;
public Base() {
service = Executors.newSingleThreadScheduledExecutor();
scheduleATassk(10);
}
public void onTimeUp() throws Exception {
if (hasMoreTime) {
scheduleATassk(newCalculatedDuration);
} else {
System.out.println("TIMER IS UP");
}
}
protected void scheduleATassk(long duration) {
service.schedule(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
onTimeUp();
}
}, duration, TimeUnit.MILLISECONDS);}
}
}

How to get a success with Junit and timeout?

#Test (expected=TimeoutException.class,timeout=1000)
public void fineForFiveSeconds() {
foo.doforever();
fail("This line should never reached");
}
This is my test code.
All I want is to run doforever() for some time period then make the test succeed.
Try this:
Execute the logic in a thread, sleep and check if the thread is still alive.
#Test
public void fineForFiveSeconds() throws InterruptedException {
Thread thread = new Thread() {
#Override
public void run() {
foo.doforever();
}
};
thread.start();
//Let the current thread sleep (not the created thread!)
Thread.sleep(5000);
assertTrue(thread.isAlive());
}

How do I pause Threads properly with wait() and notify()

I want to have a class that starts a Thread and provides methods to pause and continue this Thread. My first approach was to have flag, which loops a sleep method as long as the value is true. Something like :
public class Bot {
private Thread t ;
private boolean isPaused;
public Bot(){
t = new Thread(new Runnable(){
#Override
public void run() {
while (true) {
System.out.println("Hi");
while(isPaused){
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
});
t.start();
}
public void pauseBot(){
isPaused = true;
}
public void continueBot(){
isPaused = false;
}
}
But since the Thread is still running and wasting CPU, I dont find this to be a good solution. How would this look with wait() and notify().
I had a look at various tutorials about that topic but somehow I couldnt apply them to my issue.
Everytime I tried it I either got IllegalMonitorStateException or the code stopped my whole application and not just the Thread I wanted to be stopped.
Another question I have is: How do prevent the Thread from beeing paused at a critical moment e.g.
Runnable r = new Runnable(){
#Override
public void run() {
while(true){
task1();
task2();
//Thread mustn't be stopped from here....
task3();
task4();
task5();
task6();
task7();
//... to here
task8();
task9();
task10();
}
}
};
Because when task3() .... task7() deal with something that would expire while the Thread is paused there must be a way to let the Thread finish task7() until it pauses.
I hope you can help me with my issue.
Thanks in advance,
Flo
So given this is your Thread class:
public class MyThread extends Thread
{
First, you need an lock object. This object can be everything, and if you use an existing object this takes less memory. Also define a flag if the bot should be paused.
public Object lock = this;
public boolean pause = false;
Now, define a pause() and continue() method for the thread. This sets the pause flag.
public void pause ()
{
pause = true;
}
public void continue ()
{
pause = false;
Here you need to wake up the thread. Note the synchronized on the lock object so that you don't get an IllegalMonitorStateException.
synchronized (lock)
{
lock.notifyAll();
}
}
No, define a method that automatically pauses the thread when it should be paused. You might call this at every moment when the thread can be paused.
private void pauseThread ()
{
synchronized (lock)
{
if (pause)
lock.wait(); // Note that this can cause an InterruptedException
}
}
Now, you can define your thread in the run() method:
public void run ()
{
task1();
task2();
pauseThread();
task3();
task4();
task5();
task6();
task7();
pauseThread();
task8();
task9();
task10();
}
}

Which is the neatest and/or most effective approach to kill a thread

I have a task x that is executed continuously in a thread which will only stop when the boolean changes it's state to true. I have done some reading and there are 3 ways that I approach when killing threads that are in the code below. Which of the 3 methods is effective ? And if none of them aren't effective or correct kindly suggest a proper approach with some code for reference.
Below is the code :
public class MyTest {
private static class transaction {
private String param1,param2,param3, param4, param5;
public transaction (String param1,String param2,String param3,String param4,String param5){
this.param1=param1;
this.param2=param2;
this.param3=param3;
this.param4=param4;
this.param5=param5;
}
public String getParam1(){
return this.param1;
}
public String getParam2(){
return this.param2;
}
public String getParam3(){
return this.param3;
}
public String getParam4(){
return this.param4;
}
public String getParam5(){
return this.param5;
}
}
public static void processBatch(String workerName){
try{
java.util.List <transaction> transactions= new java.util.LinkedList<transaction>();
java.sql.ResultSet dbtrx=Database.db.execQuery((Object)"dbname.procname");
while(dbtrx.next()){// Takes a snapshot of the pending payments in the table and stores it into the list.
Object obj=new transaction (dbtrx.getString("col1"), dbtrx.getString("col2"), dbtrx.getString("col3"), dbtrx.getString("col4"), dbtrx.getString("col5"));
transactions.add((transaction)obj);
obj=null;
}
java.util.Iterator<transaction> iterate= transactions.iterator();
/* Processes the pending batch payments*/
while(iterate.hasNext()){
transaction trx=iterate.next();
/*Calls posting function here*/
System.out.println(workerName+":- Param1 : "+trx.getParam1()+" - Param2 : " +trx.getParam2()+
" - Param3 : "+ trx.getParam3()+" - Param4 : "+ trx.getParam4()+" - Param5 : "+ trx.getParam5());
iterate.remove();
}
/*cleaning object references*/
dbtrx=null;
transactions=null;
iterate=null;
}catch(Exception e){
e.printStackTrace();
}
}
public static void main(String [] args) throws InterruptedException{
volatile boolean stop=false;
Object hold= new Object();
new Thread("Batch Worker A"){
#Override
public void run(){
while(true){
if(stop!=true){
processBatch(Thread.currentThread().getName());
}else{
try{
Thread.sleep(0);
Thread.currentThread().interrupt();
}catch(java.lang.InterruptedException e){
Thread.currentThread().interrupt();
break;
}
}
}
}}.start();
new Thread("Batch Worker B"){
#Override
public void run(){
try{
while(stop!=true){
processBatch(Thread.currentThread().getName());
}
Thread.sleep(0);
Thread.currentThread().interrupt();
}catch(java.lang.InterruptedException e){
Thread.currentThread().interrupt();
}
}}.start();
new Thread("Batch Worker C"){
#Override
public void run(){
while(!Thread.currentThread().isInterrupted()){
if(stop!=true){
processBatch(Thread.currentThread().getName());
}else{
Thread.currentThread().interrupt();
}
}
}}.start();
}
}
}
The recommended approach is to use the thread's interrupted flag to signal the thread loop to terminate. There's no reason to use two flags (stopped and the interrupted flag) where one will do, and you don't seem to be using the interrupted flag for anything else.
See the Java tutorial subject Interrupts for a more extensive discussion and examples.
Why not simply this way:
new Thread("Batch Worker A"){
#Override
public void run() {
while(!stop){
processBatch(Thread.currentThread().getName());
}
}
}}.start();
Alternatively, use Thread.interrupt() like so:
new Thread("Batch Worker A"){
#Override
public void run() {
while(!interrupted()){
processBatch(Thread.currentThread().getName());
}
}
}}.start();
but then you need to keep reference to all the threads, and interrupt them all, so the boolean flag might be simpler (be sure to make it volatile).
In all of your examples, you aren't really killing the thread, you are stopping the batch from processing more items.
To understand the difference, note that none of your methods would actually stop the thread while the thread is within the processBatch function.
There are some things to take note of:
There is no point in calling Interrupt() on your current thread. The idea behind Interrupt is for external threads to call it. In your case, you can just as well throw an exception, or return from the run() function (which would shut down the thread automatically).
Even interrupt() can't in many situations stop a thread if that thread is locked outside java ,such as thread waiting for IO (if not using NIO), including a socket, which is what the database connection is, you'll need to design a different way to stop a thread inside IO (usually by doing a timeout, but there are other ways).
if you goal is simply to stop the next batch from happing use the code from Joonas :
new Thread("Batch Worker A"){
#Override
public void run() {
while(!stop){
processBatch(Thread.currentThread().getName());
}
}
}}.start();
if your goal is to interrupt the process while running the batch, you can just as well do:
public static void main(String[] args) {
var t =new Thread("Batch Worker A"){
#Override
public void run() {
processBatch(Thread.currentThread().getName());
}
}.start();
t.interrupt();
}
in general interrupt is the preferred method, and using a local scoped variable and anonymous classes is a really bad idea (use a static variable, or better an injected interface with a function to check if the thread should continue).

Waiting for all Runnables submitted to SWT UI thread with Display::asyncExec() to finish

Is there a way to wait for all Runnables submitted to the SWT UI Thread via asyncExec(...) to finish?
Background:
I have a long-running operation, which among other things is triggering events that in turn submit Runnables to the SWT UI thread via the asyncExec(...) instance method of Display.
The progress of the long-running operation is shown in a ProgressMonitorDialog, and I would like to close the dialog only after the UI thread has finished executing the Runnables.
Changing the calls from asyncExec(...) to syncExec(...) is not an option, as the latter is not desired when the events are triggered from other contexts.
org.eclipse.swt.widgets.Display.readAndDispatch() will process an event from the event queue and return false if there are no more events to process. But you probably don't want to use this as it processes an event.
asyncExec(*) is a FIFO queue (although OS graphics events supersede the asyncExecs), so you could do most of your long-running op processing and then place a final asyncExec in the queue:
final boolean[] done = new boolean[1];
Runnable r = new Runnable() {
public void run() {
done[0] = true;
}
};
// now wait for the event somehow. The brute force method:
while (!done[0]) {
Thread.sleep(200);
}
In theory, all of the other asyncExecs spawned from your long running op will be finished by the time you get to the last one.
EDIT: potential other option
Create your own org.eclipse.core.runtime.jobs.Job and then join() it at the end:
public static class RefCountJob extends Job {
public RefCountJob() {
super("REF_COUNT");
}
int count = 0;
public void increment() {
count++;
}
public void decrement() {
count--;
}
#Override
protected IStatus run(IProgressMonitor monitor) {
monitor.beginTask("WAITING", IProgressMonitor.UNKNOWN);
while (count > 0) {
Thread.sleep(200);
monitor.worked(1);
}
monitor.done();
return Status.OK_STATUS;
}
}
To use it, increment() it every time you are going to fire off events, and have them decrement it when they're done (You have to make sure they decrement it no matter what exception is thrown :-)
RefCountJob ref = new RefCountJob();
// ... do stuff, everybody increments and decrements ref
ref.increment();
// ... do more stuff
ref.increment();
// at the end of your long-running job
ref.schedule();
ref.join();
Thanks, I ended up with the following. I think it is a pretty clean solution. By the way I would upvote your answer if I had enough reputation for that :)
public class SWTThreadingUtils
{
public static void waitForAsyncExecsToFinish(Display display)
{
Object waitObj = new Object();
display.asyncExec(new DummyRunnable(waitObj));
synchronized (waitObj)
{
try {
waitObj.wait();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
private static class DummyRunnable implements Runnable
{
private Object waitObj;
public DummyRunnable(Object waitObj)
{
this.waitObj = waitObj;
}
#Override
public void run()
{
synchronized (waitObj)
{
waitObj.notify();
}
}
}
}

Categories