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

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);}
}
}

Related

How to call method in every minute using Java but in background without affect current process?

When program will be started then automatically call one method in every minute in background without using thread.
class Abc
{
main()
{
do something......
}
}
class xyz
{
public void show()
{
call every 1 minute in background
do something.....
with out affect main method
}
}
You can't do 2 things at one time with only 1 thread. You have to create another thread.
Assuming that you need to call show() every 1 min from main without interfering main() code
class Abc
{
main()
{
Thread mythread = new Thread()
{
xyz myClass = new xyz();
public void run()
{
while(true)
{
myClass.show() // this will execute
thread.sleep(60000); // this will pause for a bit but wont affect your main code, add this in between try and catch to pause this thread alone withotu affecting main one for 1 min and it goes again and calls show()
}
}
}
do something......
}
}
class xyz
{
public void show()
{
// whatever you type here will now run every 1 min, without affecting your main code
}
}
You can use ScheduledExecutorService for this task.
public static class Scheduler {
private Runnable task;
private ScheduledExecutorService executorService;
public Scheduler(Runnable task, ScheduledExecutorService executorService) {
this.task = task;
this.executorService = executorService;
}
public void start(long startDelay, long period ) {
executorService.scheduleAtFixedRate(task, startDelay, period, TimeUnit.MINUTES);
}
}

Changing intervall of periodic action with Thread and Thread.sleep

I have a periodic action which I want to do in a defined intervall (granularity in seconds). So I used a thread which sleeps for the requested time and then do the action and then sleep again and so on..
public class DiscoveryThread extends Thread
{
private int deviceDiscoveryIntervall = 1;
public void setDeviceDiscoveryIntervall(int seconds)
{
deviceDiscoveryIntervall = seconds;
}
#Override
public void run()
{
while(!isInterrupted())
{
//do there the action
try
{
sleep(deviceDiscoveryIntervall*1000);
}
catch (InterruptedException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
Now I want to set sometimes a new intervall for the periodic action. If the intervall was before 10 seconds and I set it 5 seconds after the last action to one second, I have to wait anyway 5 seconds until the next action, but It should do the action in this case immediately.
So how should I do this? If I use the interrupted() method, the sleep method will throw an InterruptedException and I could do the action immediately. But then I have to use an own flag for the whole loop as I don't want to exit the thread. And how is about calling the sleep() method again after an InterruptedException, is the interrupted flag still set? Am I able to interrupt the sleep() method again? And how about using the interrupted() method for not stopping the thread, is this not kind of missusing it?
The thread should wait on an object with the correct timeout, call notifyAll on the object when you want the thread to wake up early.
You should consider using a ScheduledExecutorService for anything like this though rather than trying to roll your own.
Use a ScheduledExecutorService:
private final Runnable r = new Runnable() {
#Override
public void run() {
// ...
}
};
private final ScheduledExecutorService ses =
Executors.newSingleThreadScheduledExecutor();
ScheduledFuture<?> sf = ses.scheduleAtFixedRate(r, 0, 10, TimeUnit.SECONDS);
// change to 5 sec: cancel and reschedule
sf.cancel();
sf = ses.scheduleAtFixedRate(r, 0, 5, TimeUnit.SECONDS);

How to stop a thread as soon as a certain amount of time expires? [duplicate]

This question already has answers here:
How to properly stop the Thread in Java?
(9 answers)
Closed 9 years ago.
I am having a problem trying to stop a thread instantly after a certain amount of time has elapsed, because thread.stop and similar others have been depreciated.
The thread that I am trying to stop uses my mouse and I need to stop it so that I can use my mouse in other ways.
What I was thinking is the code below, which was just to make another thread to watch how long the main thread has been running and if it is alive, stop it, but I can't accomplish this.
public void threadRun(int a) {
Thread mainThread = new Thread(new Runnable() {
#Override
public void run() {
// does things with mouse which may need to be ended while they
// are in action
}
});
Thread watchThread = new Thread(new Runnable() {
#Override
public void run() {
if (timeFromMark(mark) > a) {
if (mainThread.isAlive()) {
// How can I stop the mainThread?
}
}
}
});
}
You need to define a class for your second thread that extends runnable and pass the first thread as an argument.
Then you can stop the first thread.
But instead of doing this manually, have a look at the Java ThreadPoolExecuter and its awaitTermination(long timeout, TimeUnit unit) method. (http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ThreadPoolExecutor.html )
Will save a lot of work.
ExecutorService executor = Executors.newFixedThreadPool(1);
Runnable r = new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
try {
System.out.println("doing stuff");
Thread.sleep(10000);
System.out.println("finished");
} catch (InterruptedException e) {
System.out.println("Interrupted before finished!");
}
}
};
executor.execute(r);
executor.shutdown();
try {
executor.awaitTermination(1, TimeUnit.SECONDS);
executor.shutdownNow();
} catch (InterruptedException e) {
//
}
System.out.println("Thread worker forced down. Continue with Application...");
Produces:
doing stuff
Interrupted before finished!
Thread worker forced down. Continue with Application...
Last two messages are nearly equal in terms of time and may change positions (its two different threads, continuing)
Java has deprecated methods for explicitly killing another thread (like Thread.stop / Thread.destroy). The right way is to make sure the operations on the other thread can handle being told to stop (for example, they expect an InterruptedException, which means you can call Thread.interrupt() in order to stop it).
Taken from How do I kill a thread from another thread in Java?
Killing/stopping threads is a bad idea. That's why they deprecated those methods. It's better to ask the thread to stop. E.g., something like the example below. (But note: if "do_something()" takes a long time, then you might want to use an interrupt to abort whatever it is.)
import java.util.concurrent.atomic.AtomicBoolean;
public class Stoppable {
private AtomicBoolean timeToDie = new AtomicBoolean(false);
private Thread thread;
public void start() {
if (thread != null) {
throw new IllegalStateException("already running");
}
thread = new Thread(new Runnable() {
public void run() {
while (!timeToDie.get()) {
// do_something();
}
}
});
thread.start();
}
public void stop() throws InterruptedException {
timeToDie.set(true);
thread.join();
thread = null;
}
}

Wait in Main Thread for Quartz Scheduler to Finish

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
}

Synchronize two timers with multiple instances (Java)

I'm a newbie in Java and I haven't work with threads in past. Now I have a really tricky issue for my level of knowledge.
I have developed two functionalities the "Send mail" and the "Check mail". Each user register his preferences and the system creates two catalogues with many instructions for periodic work like
A) send message every 1500 msec
B) send message every 1800 msec
C) send message every 3000 msec
And
A) check message every 2000 msec
B) check message every 6000 msec
C) check message every 8000 msec
I tried many ways with threads but I fail to do it work.
My question is which is the best way to synchronize them? Below is code from my last effort using threads.
public class MailCreatorThread extends Thread {
#Override
public void run() {
CreateMail(_date); //creates a mail with _date as subject
}
}
public class GPSThread extends Thread {
#Override
public void run() {
// TODO Auto-generated method stub
while (!_isTimeToStop) {
try {
while (_servicesToUpdate.size() == 0) {
Thread.sleep(500);
}
_currentService = (MyService) _servicesToUpdate.get(0)
.clone();
_servicesToUpdate.remove(0);
MailCreatorThread mailCreatorThread = new MailCreatorThread();
mailCreatorThread.start();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
public class CheckServicesThread extends Thread {
#Override
public void run() {
// TODO Auto-generated method stub
while (!_isTimeToStop) {
try {
Thread.sleep(1000);
for (int j = 0; j < _servicesList.length; j++) {
MyService currentService = ((MyService) _servicesList[j]);
if (myService.getTimeToNextUpdate() - 1000 <= 0) {
_servicesToUpdate
.add((MyService) currentService
.clone());
currentService
.setTimeToNextUpdate(currentService
.getUpdatePeriod());
} else {
currentService
.setTimeToNextUpdate(currentService
.getTimeToNextUpdate() - 1000);
}
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
stopSelf();
}
}
You can use a ScheduledExecutorService to run thos periodic tasks. The syntax is fairly straightforward:
Runnable check = new Runnable() {
public void run() {
checkMessage();
}
}
Runnable send = new Runnable() {
public void run() {
sendMessage();
}
}
//since what you are doing is mostly I/O you probably want to have
//more than one thread available so that if one operation blocks,
//the other ones can be launched in parallel
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(10);
scheduler.scheduleAtFixedRate(check, 0, 1500, MILLISECONDS);
scheduler.scheduleAtFixedRate(send, 0, 6000, MILLISECONDS);
Note: Timer mentioned in Ozzy's answer should not be used any more as it has been improved in Java 1.5 by ScheduledThreadPoolExecutor, as explained in Timer's javadoc :
Java 5.0 introduced the java.util.concurrent package and one of the concurrency utilities therein is the ScheduledThreadPoolExecutor which is a thread pool for repeatedly executing tasks at a given rate or delay. It is effectively a more versatile replacement for the Timer/TimerTask combination, as it allows multiple service threads, accepts various time units, and doesn't require subclassing TimerTask (just implement Runnable). Configuring ScheduledThreadPoolExecutor with one thread makes it equivalent to Timer.
In java you have built-in Timer and TimerTask classes to help you repeat a task in a separate thread.
This will create a Timer which will create its own background Thread:
Timer t = new Timer();
You can then schedule as many tasks as you want to that timer, they will share the timer's own thread.
This is how you can schedule a single task on the timer thread, after a delay of 2000ms = 2s:
t.schedule(new TimerTask() {
#Override
public void run() {
//task to perform
}
}, 2000);
This is how you can schedule a repeated task on the timer thread, after a delay of 1s, and repeat the task at 1.5s intervals:
t.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
//task to perform every 1.5 seconds
}
}, 1000, 1500);
Now you have a choice to schedule both tasks (checkMail, sendMail) to the same Timer (same thread) or give them each their own Timer (separate threads).
For more info, refer to the java docs (http://docs.oracle.com/javase/6/docs/api/java/util/Timer.html)
Hope this helps.

Categories