I am trying to build multiple Timers and scheduled independent tasks for each of them. I have a constructor for holding a Timer and its variable. Then, I will call them one by one but I found that the variables, passed to the Timer constructor, are overrode by each other. I already initiate each Timer as a new instance but still cannot solve the issue. How can I make sure the timers are run independently?
Code:
public class App
{
public static void main( String[] args )
{
System.out.println( "Hello World!" );
TimerTrigger.INSTANCE.runTimer();
}
}
To Trigger the timer:
public enum TimerTrigger {
INSTANCE;
private TimerTrigger(){}
public void runTimer(){
for (int i = 0; i < 3; i++) {
System.out.println( "Initiaizing Timer " + i );
TimerConstructor tmpTimer = new TimerConstructor();
varObjectvo timerVariable = new varObjectvo();
timerVariable.setIndex(i);
// timerList.add(tmpTimer);
tmpTimer.start(timerVariable); //timerVariable is a value object
}
}
}
The Constructor of timer:
import java.util.Timer;
import java.util.TimerTask;
import java.util.Date;
public class TimerConstructor{
private static varObjectvo timerVO = null;
Timer timer = null;
public void start(varObjectvo obj) {
timer = new Timer("Timer_" + obj.getIndex()); // will be Timer_1/2/3
timerVO = obj;
TimerChecker task = new TimerChecker();
timer.scheduleAtFixedRate(task, new Date(), 10000);
}
private class TimerChecker extends TimerTask {
public void run() {
System.out.println("It is timer " + timerVO.getIndex() + " from: " + timer.toString());
}
}
}
The value object class:
public class varObjectvo{
private Integer index;
public void setIndex(Integer i){
this.index = i;
};
public Integer getIndex(){
return this.index;
};
}
Output:
Hello World!
Initiaizing Timer 0
Initiaizing Timer 1
It is timer 0 from:java.util.Timer#6b45c377
It is timer 1 from:java.util.Timer#17481b7c
Initiaizing Timer 2
It is timer 2 from:java.util.Timer#48e94d09
It is timer 2 from:java.util.Timer#17481b7c
It is timer 2 from:java.util.Timer#48e94d09
It is timer 2 from:java.util.Timer#6b45c377
In short, seems the variables in former Timer are being overwritten by the later Timer.
As commented, your main problem seems to be making your variable timerVO static.
The static keyword means you want only one such value rather than each instance having its own value known by that name. In other words, static is not object-oriented.
So each time you execute timerVO = obj;, you replace the previously stored value with the current one. You have only a single timerVO in your entire app, because you marked it static. That timerVO can contain only a single value, the value last assigned.
You said:
I already initiate each timer as new instance but still cannot solve the issue.
But… all those timer objects you instantiated share the same single static timerVO object.
Minor issue: Class names start with an uppercase letter. So public class varObjectvo should be public class VarObjectvo.
Another minor issue: Naming a method “…Constructor” is confusing. That word has a very specific crucial meaning in Java. A constructor in Java is always named the same as the class name.
Bigger picture: You are not taking advantage of modern Java. If you read carefully the Javadoc of Timer and TimerTask classes, you’ll see they were supplanted years ago by the Executors framework.
To use executors, define your tasks as implementing either Runnable or Callable. Then establish a ScheduledExecutorService. Submit instances of your tasks to that service for repeated execution.
Search Stack Overflow to learn more. Scheduled executor service has been covered many many times already.
Some rough untested code follows.
class Counter implements Runnable {
private final AtomicInteger count = new AtomicInteger( 0 ) ;
void run() { this.count.incrementAndGet() ; }
int getCount() { return this.count.get() ; }
}
Instantiate.
Counter countEvery5Seconds = new Counter() ;
Counter countEvery42Seconds = new Counter() ;
Initialize your scheduled executor service.
ScheduledExecutorService ses = Executors.newSingleThreadScheduledExecutor() ;
Schedule your tasks.
ScheduledFuture<?> count5 =
scheduler.scheduleAtFixedRate( countEvery5Seconds, 0, 5, TimeUnit.SECONDS);
ScheduledFuture<?> count42 =
scheduler.scheduleAtFixedRate( countEvery42Seconds, 0, 42, TimeUnit.SECONDS);
Be sure to shutdown your executor service. See discussions in many other Answers. See boilerplate code in Javadoc.
Related
I have a singleton class that creates a thread on instance creation. Only one object of this class is created and the thread is scheduled to run every 12 hours and print the given statement. In some cases after the first 12h the thread is invoked every 4-5 seconds. I am confused as to why this happens as I have configured the scheduler to run once every 12 hours and not every 4-5 seconds. Is there any config I have missed or is the scheduler wrong configured?
the singleton class,
import java.time.Instant;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
public class ThreadSchedulerTest {
private static final ThreadSchedulerTest test = new ThreadSchedulerTest();
private ThreadSchedulerTest (){createThread();}
private void createThread() {
Runnable renewer = () -> {
System.out.println("Running ok , time is : "+ Instant.now());
};
Executors.newSingleThreadScheduledExecutor(new
ThreadSchedulerThreadFactory("thread1")).scheduleAtFixedRate(
renewer, 0, 12, TimeUnit.HOURS);
}
static class ThreadSchedulerThreadFactory implements ThreadFactory {
private final String name;
public ThreadSchedulerThreadFactory(final String name) {
this.name = name;
}
#Override
public Thread newThread(Runnable r) {
Thread thread = new Thread(r, name);
thread.setDaemon(true);
return thread;
}
}
}
Can someone please help clarify this issue?
You will find it easier to test the if you change the TimeUnit to SECONDS and make the Runnable print hashcode of the instance:
Runnable renewer = () -> {
System.out.println("Running ok instance="+ThreadSchedulerTest.this.hashCode()+", time is : "+ Instant.now());
};
Your problem with repeating every 4-5 seconds is probably that you have created two instances of ThreadSchedulerTest. The above message fix will confirm.
The code you have provided will not run as you have recursive definition of the constructor and member variable. Thus every instance of ThreadSchedulerTest executes second constructor ThreadSchedulerTest test = new ThreadSchedulerTest(); - which then instantiates a new member test:
new ThreadSchedulerTest()
| Exception java.lang.StackOverflowError
| at ThreadSchedulerTest.<init> (#5:2)
You can fix my making this declaration - test is static and constructor private so only one instance is ever constructed:
public class ThreadSchedulerTest {
static final ThreadSchedulerTest test = new ThreadSchedulerTest();
private ThreadSchedulerTest () {
createThread();
}
...
I need a way to have a timer that is running on start command. Initially, the timer will be told how long to run for. However, i need a way to change this mid-way in between. If a user specifies that they would like to change the time the timer runs (by either decreasing, increasing or even ending the timer all together). I also want to be able to update the UI by showing the current time in minutes:seconds format.
The user may also want to spawn multiple timers - so they should have a way of monitoring and accessing different timers which they have set..
Currently this is what i have - from what i can tell, it works.. but i don't feel too good about it :S how can i make this better? Or what is the right way of doing this? Keep in mind that there will be other things happening while this timer is running - for instance, the user may be interacting with the UI and executing different commands un-related to the timer..
I really don't know much about threads or threading... so this is relatively new to me..
thanks in advance!
In Main:
//every time they request for a new timer, i will instantiate a new Task object..
Task task = new Task();
task.run()
task.getTaskTime();
Task.java:
public class Task extends Thread{
#Override
public void run()
{
timer = new Timer(60 * 60);
timer.start();
}
public boolean getTImerRunning() {
return timer.timerRunning;
}
public double getTaskTime() {
return timer.currentTime;
}
}
In Timer.java:
public class Timer extends Thread {
public static final int DEFAULT_TIMER = 180;
private long startMinute = 0;
private int _timer;
public double currentTime = 0;
public boolean timerRunning = true;
Timer(int timer) {
this._timer = timer;
}
Timer() {
this._timer = DEFAULT_TIMER;
}
#Override
public void run(){
long start = System.currentTimeMillis();
startMinute = start;
while(elapsedTime() <= this._timer) {
currentTime = elapsedTime();
}
timerRunning = false;
}
/**
* Return elapsed time since this object was created.
*/
private double elapsedTime() {
long now = System.currentTimeMillis();
return (now - startMinute);
}
}
Every time the user creates a "timer", do not create a new Task, but create an object MyTimer that holds the creation time and countdown duration and add the instance to an ArrayList.
The very first and only the first time, a user creates a timer you will create a task that executes every second. When that task executes it updates the UI and cycles through the ArrayList and updates each instance of MyTimer by adjusting the countdown duration.
That should keep things simple and reduce overhead.
Good Luck!
I have a thread which is in charge of doing some processes. I want make it so that these processing would be done every 3 seconds. I've used the code below but when the thread starts, nothing happens.
I assumed that when I define a task for my timer it automatically execute the ScheduledTask within time interval but it doesn't do anything at all.
What am I missing?
class temperatureUp extends Thread
{
#Override
public void run()
{
TimerTask increaseTemperature = new TimerTask(){
public void run() {
try {
//do the processing
} catch (InterruptedException ex) {}
}
};
Timer increaserTimer = new Timer("MyTimer");
increaserTimer.schedule(increaseTemperature, 3000);
}
};
A few errors in your code snippet:
You extend the Thread class, which is not really good practice
You have a Timer within a Thread? That doesnt make sense as the a Timer runs on its own Thread.
You should rather (when/where necessary), implement a Runnable see here for a short example, however I cannot see the need for both a Thread and Timer in the snippet you gave.
Please see the below example of a working Timer which will simply increment the counter by one each time it is called (every 3seconds):
import java.util.Timer;
import java.util.TimerTask;
public class Test {
static int counter = 0;
public static void main(String[] args) {
TimerTask timerTask = new TimerTask() {
#Override
public void run() {
System.out.println("TimerTask executing counter is: " + counter);
counter++;//increments the counter
}
};
Timer timer = new Timer("MyTimer");//create a new Timer
timer.scheduleAtFixedRate(timerTask, 30, 3000);//this line starts the timer at the same time its executed
}
}
Addendum:
I did a short example of incorporating a Thread into the mix. So now the TimerTask will merely increment counter by 1 every 3 seconds, and the Thread will display counters value sleeping for 1 seconds every time it checks counter (it will terminate itself and the timer after counter==3):
import java.util.Timer;
import java.util.TimerTask;
public class Test {
static int counter = 0;
static Timer timer;
public static void main(String[] args) {
//create timer task to increment counter
TimerTask timerTask = new TimerTask() {
#Override
public void run() {
// System.out.println("TimerTask executing counter is: " + counter);
counter++;
}
};
//create thread to print counter value
Thread t = new Thread(new Runnable() {
#Override
public void run() {
while (true) {
try {
System.out.println("Thread reading counter is: " + counter);
if (counter == 3) {
System.out.println("Counter has reached 3 now will terminate");
timer.cancel();//end the timer
break;//end this loop
}
Thread.sleep(1000);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
}
});
timer = new Timer("MyTimer");//create a new timer
timer.scheduleAtFixedRate(timerTask, 30, 3000);//start timer in 30ms to increment counter
t.start();//start thread to display counter
}
}
import java.util.Timer;
import java.util.TimerTask;
public class ThreadTimer extends TimerTask{
static int counter = 0;
public static void main(String [] args) {
Timer timer = new Timer("MyTimer");
timer.scheduleAtFixedRate(new ThreadTimer(), 30, 3000);
}
#Override
public void run() {
// TODO Auto-generated method stub
System.out.println("TimerTask executing counter is: " + counter);
counter++;
}
}
In order to do something every three seconds you should use scheduleAtFixedRate (see javadoc).
However your code really does nothing because you create a thread in which you start a timer just before the thread's run stops (there is nothing more to do). When the timer (which is a single shoot one) triggers, there is no thread to interrupt (run finished before).
class temperatureUp extends Thread
{
#Override
public void run()
{
TimerTask increaseTemperature = new TimerTask(){
public void run() {
try {
//do the processing
} catch (InterruptedException ex) {}
}
};
Timer increaserTimer = new Timer("MyTimer");
//start a 3 seconds timer 10ms later
increaserTimer.scheduleAtFixedRate(increaseTemperature, 3000, 10);
while(true) {
//give it some time to see timer triggering
doSomethingMeaningful();
}
}
I think the method you've used has the signature schedule(TimerTask task, long delay) . So in effect you're just delaying the start time of the ONLY execution.
To schedule it to run every 3 seconds you need to go with this method schedule(TimerTask task, long delay, long period) where the third param is used to give the period interval.
You can refer the Timer class definition here to be of further help
http://docs.oracle.com/javase/1.4.2/docs/api/java/util/Timer.html
Timer & TimerTask are legacy
The Timer & TimerTask classes are now legacy. To run code at a certain time, or to run code repeatedly, use a scheduled executor service.
To quote the Timer class 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.
Executor framework
In modern Java, we use the Executors framework rather than directly addressing the Thread class.
Define your task as a Runnable or Callable. You can use compact lambda syntax seen below. Or you can use conventional syntax to define a class implementing the Runnable (or Callable) interface.
Ask a ScheduledExecutorService object to execute your Runnable object’s code every so often.
ScheduledExecutorService scheduledExecutorService = Executors.newSingleThreadScheduledExecutor() ;
Runnable task = () -> {
System.out.println( "Doing my thing at: " + Instant.now() );
};
long initialDelay = 0L ;
long period = 3L ;
TimeUnit timeUnit = TimeUnit.SECONDS ;
scheduledExecutorService.submit( task , initialDelay, period , timeUnit ) ;
…
scheduledExecutorService.shutdown() ; // Stops any more tasks from being scheduled.
scheduledExecutorService.awaitTermination() ; // Waits until all currently running tasks are done/failed/canceled.
Notice that we are not directly managing any Thread objects in the code above. Managing threads is the job of the executor service.
Tips:
Always shutdown your executor service gracefully when no longer needed, or when your app exits. Otherwise the backing thread pool may continue indefinitely like a zombie 🧟♂️.
Consider wrapping your task's working code in a try-catch. Any uncaught exception or error reaching the scheduled executor service results in silently halting the further scheduling of any more runs.
I'm calling this tasks:
TimerTask taskA = new ThreadA(this);
TimerTask taskB = new ThreadB(this);
tasks.add(taskA);
tasks.add(taskB);
timer.schedule(taskA, 10000);
timer.schedule(taskB, 5000);
And here are the two TimerTasks:
public class ThreadA extends TimerTask {
private Ghost ghost;
public GhostThread(Ghost ghost) {
this.ghost = ghost;
}
#Override
public void run() {
ghost.stopBeingDeadAndBeAwesomeAgain();
}
}
public class ThreadB extends TimerTask {
private Ghost ghost;
public WarnThread(Ghost ghost) {
this.ghost = ghost;
}
#Override
public void run() {
ghost.beDeadAgain();
}
}
As you can see, I just call a method after 5 resp. 10 seconds. From time to time I would like to pause the "countdown". This means i want that the time until the 5 seconds are passed isn't running anymore. And then in a later point in time, I would like to resume it.
How can I achieve that??
The simplest solution would be to simply make a copy of the TimerTask, cancel it to pause, purge if you want, and then reschedule it to resume.
// pause
long timeLeft = 5000 - (new Date().getTime() - taskB.scheduledExecutionTime());
ThreadB taskBpaused = taskB.clone();
taskB.cancel();
timer.purge();
taskB = taskBpaused;
// resume
timer.schedule(taskB, timeLeft, ...);
Important note: if the task hasn't run yet, then this won't work. Google's documentation states that if it hasn't run, scheduledExecutionTime() will return an undefined value, and I don't have the capability to test what exactly that means at the moment. Needless to say, if you aren't sure it's already run, you'll need some kind of conditional to make sure the value isn't undefined.
import java.util.Scanner;
import java.util.Timer;
import java.util.TimerTask;
public class Boggle {
Board board;
Player player;
Timer timer;
boolean active;
static Scanner in = new Scanner(System.in);
public Boggle() {
board = new Board(4);
timer = new Timer();
}
public void newGame() {
System.out.println("Please enter your name: ");
String line = in.nextLine();
player = new Player(line);
active = true;
board.shuffle();
System.out.println(board);
timer.schedule(new timesUP(), 20000);
while(active) {
String temp = in.nextLine();
player.addGuess(temp);
}
}
public void endGame() {
active = false;
int score = Scoring.calculate(player, board);
System.out.println(score);
}
class timesUP extends TimerTask {
public void run() {
endGame();
}
}
public static void main(String[] args) {
Boggle boggle = new Boggle();
boggle.newGame();
}
}
I have the above class which should perform a loop for a given length of time and afterwards invoke an instance method. Essentially I need the loop in newGame() to run for a minute or so before endGame() is invoked on the current instance. However, using the Timer class I'm not sure how I would invoke the method I need on the current instance since I can't pass any parameters to the timertasks run method?
Is there an easy way to do this or am I going about this the wrong way? (note: this is a console project only, no GUI)
==========
code edited
I've changed the code to the above following the recommendations, and it works almost as I expect however the thread still doesnt seem to end properly. I was the while loop would die and control would eventually come back to the main method. Any ideas?
Because timesUP (please change the name!) is an inner class, it already has a reference to the instance of Boggle which created it. (That wouldn't be the case if it were marked as static.) If you wanted to create an instance of timesUP associated with another instance, you'd do something like:
otherBoggle.new timesUp();
It's pretty odd syntax, admittedly :)
This doesn't fix the problem that Midhat identified, admittedly - but it means you don't need to worry about getting a reference to the outer class. Just call endGame() from within timesUP.run() and it will call it on the appropriate instance.
You have blocking console input in the thread. The running time will be dictated by that. You can have the console input in a seperate thread, and add a timer in the current thread to kill the input thread after a minute, and call this.endGame()