Run a task continuously without delay inside a Java TimerTask - java

How do I run a specific set of instructions inside the TimerTask continuously without delay for a set amount of time ? Below are the codes I am attempting to implement the above.
Timer timer = new Timer();
timer.schedule(new TimerTask() {
public void run() {
System.out.println("Test started at: " + new Date());
// Do something continuously without delay
System.out.println("Test finished at: " + new Date());
}
}, 0);

The second parameter to the schedule method is the time to begin the timer task (or delay relative to now), not the length of time that the timer will execute for.
It's not completely clear from your question but I'm assuming you want the task to start and stop at particular times (or delays relative to now) in the future. If so, the way I would approach this is to create a Thread that does the task you need. Since a TimerTask is a Runnable that is executed as a Thread once the Timer starts it, you can just use an instance of that TimerTask. Ensure that Runnable contains a settable field like running. In that Thread, run your task in a while loop like this:
public void run() {
while(running) { /* do my task */ }
}
Then, use one Timer to schedule the Runnable to start at the time you need. Use another Timer to set the running parameter of the same Thread to false at the time you want it to stop. The running parameter should be volatile to ensure that changes to it from the second timer Thread are seen by the first timer Thread immediately. So it would look something like this (not tested):
class StoppableTimerTask extends TimerTask {
private volatile boolean running = true;
public void stopRunning() { this.running = false; }
public void run() {
while(running) { /* do my task */ }
}
}
final StoppableTimerTask task = new StoppableTimerTask();
timer.schedule(task, startTime);
timer.schedule(new TimerTask() {
public void run() {
task.stopRunning();
}
}, stopTime);
Depending on what your "something" is, you may also want to look into Thread interrupts. For example, if it is doing blocking IO, your code won't loop and check the running value until the blocking IO completes. Interrupting the thread (may) cause that to happen. See http://docs.oracle.com/javase/8/docs/api/java/lang/Thread.html#interrupt--. This may or may not work, and it can be tricky to get right, so if you need this Thread to exit as close to the desired time as possible, prefer running blocking I/O and similar operations with smaller timeouts so that the thread can check whether it should continue to run more often.
UPDATE: As per the comment indicating that the task should start right away, it becomes even simpler. The initial task doesn't even need to extend TimerTask -- it can just be a regular Thread that is started immediately. The timer is only needed to stop it at the specified future time.

Related

Discord JDA How to make command be unique per user that uses it?

In essence, I have an onGuildMessageReceived method that listens for a command alarm with which a user can set a countdown to notify him with a message. They type a time amount and eventual alarm message that comes with the ping they will get after that time.
My question is, how can I make this feature work for each user separately, so other users don't overwrite previous alarm times that were already ticking?
This method is called in the main code to start the countdown.
public void StartTimer(int seconds, GuildMessageReceivedEvent event)
{
timer = new Timer();
timer.schedule(new TimerReminder(event), seconds * 1000);
}
public void StartTimer(int seconds, GuildMessageReceivedEvent event, String text)
{
timer = new Timer();
timer.schedule(new TimerReminder(event, text), seconds * 1000);
}
I have this subclass that does a block of code after the .schedule() time.
class TimerReminder extends TimerTask{
GuildMessageReceivedEvent eventtrigger;
String alarmText = "";
private TimerReminder(GuildMessageReceivedEvent event)
{
eventtrigger=event;
}
private TimerReminder(GuildMessageReceivedEvent event, String alarmArg)
{
eventtrigger=event;
alarmText=alarmArg;
}
public void run()
{
if(alarmText.isEmpty())
{
eventtrigger.getChannel().sendMessage("<#"+auth+">, ***your alarm is ringing!***🔔🔔🔔🔔").queue();
timer.cancel(); // Terminate the timer thread
}
else
{
eventtrigger.getChannel().sendMessage("<#"+auth+">:\n"+alarmText).queue();
timer.cancel(); // Terminate the timer thread
alarmText="";
}
}
}
At the end of each task, you're running cancel on the timer reference which cancels not the timer that is currently running (Unless no one else ran the command) but rather the timer object that is assigned at the moment to the timer reference which makes it seem like the timers are overwriting each other.
And even if you kept a reference to all of the timers so you could cancel them, there's no need for you to cancel the timer after the task completes, the timer terminates itself.
Furthermore, there's no need for you to keep a static reference to the timer that is currently running, or keep a reference to them at all. When you create a timer a background thread keeps a reference to the timer and the task so they won't get garbage collected. You'd be better off creating the timer as a local variable when the command is run, scheduling the timer and that's it.
If you want the ability to cancel the timers by a different command or whatever you have in mind, then you should keep a list or map with references to all the current timers so you can cancel them if needed.

Create a thread which never ends

I want to create a thread which never halts. Every second it will acquire the system time and display this on the console. This is what I have so far:
public class Test implements Runnable {
#Override
public void run() {
System.out.println(System.currentTimeMillis());
}
}
I'd like to avoid using a loop.
Using while(true) and TimeUnit.SECONDS.sleep is a possibility, but it is bad practice (as you can see from the sheer number of downvotes on this post). This SO answer gives some reasons as to why:
low level, subject to spurious wakeups
clock drift
control
intent of code
there are others.
The basic way to achieve this is to use a java.util.Timer, not to be confused with a javax.swing.Timer:
final Timer timer = new Timer("MyTimer");
timer.schedule(new TimerTask() {
#Override
public void run() {
System.out.println(System.currentTimeMillis());
}
}, 0, TimeUnit.SECONDS.toMillis(1));
You need to call timer.cancel() to stop the timer - as the timer is running a non-daemon thread your program will not exit until that is done.
A more advanced way, which allows multiple tasks to be scheduled to run at different intervals on a pool of the ScheduledExecutorService. This allows you to scheduleAtFixedRate which runs a task every second (regardless of how long it takes to run, i.e. the gap between start times is always the same) or scheduleWithFixedDelay which runs a task at one second intervals (i.e. the gap between the end of one run and the start of the next is always the same).
For example:
final ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor();
final ScheduledFuture<?> handle = executorService.scheduleAtFixedRate(new Runnable() {
#Override
public void run() {
System.out.println(System.currentTimeMillis());
}
}, 0, 1, TimeUnit.SECONDS);
To cancel the particular task you would call handle.cancel(false) (as interrupting has no effect) and to stop the executorService you would call executorService.shutdown() after which you might want to add a executorService.awaitTermination(1, TimeUnit.DAYS) to wait for all the tasks to finish.
EDIT
A comment This can be done more concisely in java 8 with lambda right? (not an expert at lambdas)
The first example, no. A Timer takes a TimerTask, this is an abstract class and not an #FunctionalInterface so a lambda is not possible. In the second case, sure:
final ScheduledFuture<?> handle = executorService.
scheduleAtFixedRate(() -> System.out.println(System.currentTimeMillis()), 0, 1, TimeUnit.SECONDS);

How can I use time in Java to manipulate code?

I'm trying to test the use of time in Java to manipulate code. So let's say I have a app with an egg. The egg won't hatch until 60 seconds have passed in the application, what method or class would I use to do this?
The Timer class should do what you are after:
A facility for threads to schedule tasks for future execution in a background thread. Tasks
may be scheduled for one-time execution, or for repeated execution at
regular intervals.
You can take a look at a simple example available here.
You can use timer in a way like this
Timer timer = new Timer();
If you want your code to run multiple times:
timer.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
// Your logic here
// Your logic will run every 60 second
System.out.println("egg hatched");
}
}, 0, 60000);
If you want it to run only one time
timer.schedule(new TimerTask() {
#Override
public void run() {
// Your logic here
System.out.println("egg hatched");
}
}, 60000);
You can read more about class timer in java here
The easiest old-fashioned single thread approach is
Thread.sleep(60*1000);
System.out.println("egg hatched");
And there is no guaranty that it print exactly after minute
System.currentTimeMillis() returns the current time of the system in milliseconds to your. So you need to create a Thread checking for the current time in a while loop an react to it.
Try run it it a separate scheduled thread;
ScheduledExecutorService scheduler =
Executors.newScheduledThreadPool(1);
Runnable hatcher = new Runnable() {
#Override
public void run() {
egg.hatch();
}
};
scheduler.schedule(hatcher, 60, TimeUnit.SECONDS);

Can you execute a task repeatedly in Java?

Is it possible to repeatedly execute a task each day, each minute, each second, each year? I want it to run like a daemon.
I need a scheduled task to search the database continuously; if it finds a certain value then it should execute a further task.
I want to ask whether it is possible to repeatedly
You can use a loop, or a ScheduleExecutorService, or a Timer, or Quartz.
each day each minute each second each year
So once a second.
I want it to run like a daemon.
I would just make it a daemon thread then. No need to make it "like" a daemon.
if it find the correct value then it should do the remaining task.
Simple enough.
Read the data, check the value and if its what you want do the rest.
The java.util.Timer and java.util.TimerTask classes, which I’ll refer to collectively as the Java timer framework, make it easy for programmers to schedule simple tasks.
public class Reminder {
Timer timer;
public Reminder(int seconds) {
timer = new Timer();
timer.schedule(new RemindTask(), seconds*1000);
}
class RemindTask extends TimerTask {
public void run() {
System.out.format("Time's up!%n");
timer.cancel(); //Terminate the timer thread
}
}
public static void main(String args[]) {
new Reminder(5);
System.out.format("Task scheduled.%n");
}
}
OR
Scheduling a Timer Task to Run Repeatedly
int delay = 5000; // delay for 5 sec.
int period = 1000; // repeat every sec.
Timer timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
public void run() {
// Task here ...
}
}, delay, period);
In order to do tasks based on time you would want to use threads. Check out this link in order to learn more about them: http://docs.oracle.com/javase/tutorial/essential/concurrency/threads.html
Hmm so the program is going to be running all the time? Might want to look into Java Timer
Perhaps a look at the java.util.Timer or Quartz Scheduler would be helpful.
A ScheduledThreadPoolExecutor might also be helpful. Look into their example code and you should be able to do it.

Swing Timer in Conjunction with Possible Long-running Background Task

I need to perform a task repeatedly that affects both GUI-related and non GUI-related objects. One caveat is that no action should performed if the previous task had not completed when the next timer event is fired.
My initial thoughts are to use a SwingTimer in conjunction with a javax.swing.SwingWorker object. The general setup would look like this.
class
{
timer = new Timer(speed, this);
timer.start();
public void actionPerformed(ActionEvent e)
{
SwingWorker worker = new SwingWorker() {
#Override
public ImageIcon[] doInBackground() {
// potential long running task
}
#Override
public void done() {
// update GUI on event dispatch thread when complete
}
}
}
Some potential issues I see with this approach are:
1) Multiple SwingWorkers will be active if a worker has not completed before the next ActionEvent is fired by the timer.
2) A SwingWorker is only designed to be executed once, so holding a reference to the worker and reusing (is not?) a viable option.
Is there a better way to achieve this?
For (1), the scheduleAtFixedRate() method on ScheduledThreadPoolExecutor might be useful. From the javadocs:
If any execution of this task takes longer than its period, then subsequent executions may start late, but will not concurrently execute.
For (2), it looks like you could define a subclass of SwingWorker and construct new instances of the subclass for each iteration, instead of instantiating an anonymous subclass.
Have you looked at using a simple Java Timer, and a ReadWriteLock to determine if a task is running when the timer triggers again ? In this situation you could simply bail out of that particular iteration and wait for the next.
Why do you use a Timer? It would be simpler to keep the 'worker' running all the time, pausing via sleep() whenever the task took too little time to complete. You can still update things in the event dispatch thread using something like the following:
Thread background = new Thread(new Runnable() {
public void run() {
while ( ! stopRequested ) {
long start = System.currentTimeMillis();
// do task
long elapsed = start - System.currentTimeMillis();
SwingUtilities.invokeLater(new Runnable() {
public void run() {
// update UI
}
});
if (elapsed < tickTime) {
Thread.sleep(tickTime - elapsed);
}
}
}
}.start();

Categories