How to access a method of a class running inside a thread? - java

I am trying to call the "checkTime" method of the "Timer" class from outside this class but that is not working... is this the right way ? how can I fix this? I am using threads
class Timer implements Runnable{
private boolean running;
private int time = 0;
public Timer(){
time = 10;
running = false;
}
public boolean isRunning(){
return running;
}
public void checkTime(){
if(isRunning()){
System.out.println("Timer is at: "+ time/1000 + " seconds");
}
}
#Override
public void run() {
try {
running = true;
Thread.sleep(1000L);
}
running = false;
}
}
}
In the other class i have something like this
Thread timer;
timer = new Thread(new Timer());
//check timer
if(cooking){
timer.checkTime();
} else{
System.out.println("The timer is set to: " + timer + " seconds");
}
break;```

Make a variable of the Timer object before you instantiate a the Thread object.
Example:
Timer timer = new Timer();
Thread thread = new Thread(timer);
// get the checkTime() value here
System.out.println(timer.checkTime());
You really need to watch out for concurrency issues as you have multiple threads managing the same variables (int time and boolean running).

Related

Using a variable inside Timer

I'm working on a program that has a prints time only when a function is called. I'm using timer for the continuous adding of seconds.
Timer gameTimer = new Timer ();
TimerTask time = new TimerTask() {
int sec = 0;
public void run()
{
sec++;
}
};
gameTimer.scheduleAtFixedRate(time, 1000, 1000);
However, I cannot use the variable sec outside the run() so I can print it. I tried to place sec outside TimerTask but of course sec++ would not work. Any help? Thanks!
Since only final variables accessible in anonymous class, but with this below hack you can achieve what you want.
final int [] result = new int[1]; // Create a final array
TimerTask time = new TimerTask() {
int sec = 0;
public void run()
{
sec++;
result[0] = sec;
}
};
// Now Print whenver you want it
System.out.println(result[0]);
This way you are not reassigning the array to a new object just changing the content inside it
Just make your own interface extending the original interface.
https://docs.oracle.com/javase/tutorial/java/IandI/nogrow.html
interface CustomTimerTask extends TimerTask {
public int getTicks();
}
CustomTimerTask time = new CustomTimerTask () {
int sec = 0;
#Override
public void run()
{
sec++;
}
#Override
public synchronized int getTicks() {
return sec;
}
};
System.out.println("The time passed is: " + time.getTicks());
Just make sure you make it synchronized because you're working with two threads now.

How to implement a Timer class in Java?

Recently, I have been developing some android apps and I found that android.os.Handler class is very suitable for implementing a .NET Timer (By that I mean System.Windows.Forms.Timer and System.Timers.Timer).
If you don't know what a .NET timer is, it's a timer that can be stopped, started at any time and its interval can be changed any time.
So I did the following:
import android.os.Handler;
public class Timer {
private Handler handler;
private boolean paused;
private int interval;
private Runnable task = new Runnable () {
#Override
public void run() {
if (!paused) {
runnable.run ();
Timer.this.handler.postDelayed (this, interval);
}
}
};
private Runnable runnable;
public int getInterval() {
return interval;
}
public void setInterval(int interval) {
this.interval = interval;
}
public void startTimer () {
paused = false;
handler.postDelayed (task, interval);
}
public void stopTimer () {
paused = true;
}
public Timer (Runnable runnable, int interval, boolean started) {
handler = new Handler ();
this.runnable = runnable;
this.interval = interval;
if (started)
startTimer ();
}
}
And it came out ok. Also, this one runs on the UI thread which means that I can use this to change graphical stuff. (I mainly use timers for those stuff)
However, this only works for android though. If I want to make a "traditional" java program, I have to use the stuff in the JDK. So I tried the following:
import java.util.Timer;
import java.util.TimerTask;
public class DotNetTimer {
private Timer timer;
private boolean paused;
private int interval;
private TimerTask task = new TimerTask () {
#Override
public void run() {
if (!paused)
runnable.run();
}
};
public Runnable runnable;
public int getInterval() {
return interval;
}
public void setInterval(int interval) {
this.interval = interval;
if (!paused) {
timer.cancel();
timer.scheduleAtFixedRate(task, interval, interval);
}
}
public void startTimer () {
timer.cancel();
timer.scheduleAtFixedRate(task, 0, interval);
}
public void stopTimer () {
paused = true;
}
public DotNetTimer (Runnable runnable, int interval, boolean started) {
timer = new Timer ();
this.runnable = runnable;
this.interval = interval;
if (started) {
paused = false;
startTimer ();
}
}
}
And I use this code to test it:
import static java.lang.System.out;
public class MyTestingClass {
static DotNetTimer timer;
public static void main(String[] args) {
Runnable r = new Runnable () {
int count = 0;
#Override
public void run() {
if (count < 5) {
count++;
out.println("Hello" + count);
} else {
timer.stopTimer();
}
}
};
timer = new DotNetTimer (r, 2000, true);
}
}
However, an IllegalStateException was thrown in the start timer method. I did some research on that and I found that java.util.Timer cannot be restarted after cancel(). And I know what you're saying, "why do you call cancel() in the startTimer() method?" If I don't call cancel(), the timer would have 2 tasks running when I call startTimer() when the timer is already started.
Any help will be appreciated.
From cancel() method in Timer class
Terminates this timer, discarding any currently scheduled tasks. Does
not interfere with a currently executing task (if it exists). Once a
timer has been terminated, its execution thread terminates gracefully,
and no more tasks may be scheduled on it.
Note that calling this method from within the run method of a timer
task that was invoked by this timer absolutely guarantees that the
ongoing task execution is the last task execution that will ever be
performed by this timer.
This method may be called repeatedly; the second and subsequent calls
have no effect.
so, internal thread of Timer is one-shot, you need to instantiate a new Timer object
You can check original source code of Timer class to understand (or replicate as you wish) how it really works
http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/util/Timer.java
I found out that there is a class in Android called Handler which can execute code with a delay. So I made use of this class to create a timer!
import android.os.Handler;
import android.support.annotation.NonNull;
import android.widget.TextView;
public class Timer implements Comparable<Timer> {
private Handler handler;
private boolean paused;
private TextView text;
private int minutes;
private int seconds;
private final Runnable timerTask = new Runnable () {
#Override
public void run() {
if (!paused) {
seconds++;
if (seconds >= 60) {
seconds = 0;
minutes++;
}
text.setText (Timer.this.toString ());
Timer.this.handler.postDelayed (this, 1000);
}
}
};
#Override
public String toString () {
if (Integer.toString (seconds).length () == 1) {
return minutes + ":0" + seconds;
} else {
return minutes + ":" + seconds;
}
}
public void startTimer () {
paused = false;
handler.postDelayed (timerTask, 1000);
}
public void stopTimer () {
paused = true;
}
public void resetTimer () {
stopTimer ();
minutes = 0;
seconds = 0;
text.setText (toString ());
}
public Timer (TextView text) {
this.text = text;
handler = new Handler ();
}
public Timer (TextView text, String parseString) {
this (text);
String[] splitString = parseString.split (":");
minutes = Integer.parseInt (splitString[0]);
seconds = Integer.parseInt (splitString[1]);
}
#Override
public int compareTo(#NonNull Timer another) {
int numberOfSeconds = seconds + minutes * 60;
int anotherNumberOfSeconds = another.seconds + another.minutes * 60;
return ((Integer)numberOfSeconds).compareTo (anotherNumberOfSeconds);
}
}
And it has a really simple interface. Very easy to use.

Creating a timer and cannot restart it

I've created GUI timer, it runs exactly how I wanted it to. I have a stop and pause button, when I stop or pause the timer and restart a new one I get Exception in thread "AWT-EventQueue-0" java.lang.IllegalStateException: Task already scheduled or cancelled
I'm unsure what I'm suppose to do I've read you cant reuse tasks, but I have no clue to solve this. Can someone PLEASE help me out I'm going crazy over this, I always seem to fix one problem but another one pops up.
Heres part of my code which does the countdown
private TimerTask task = new TimerTask(){
#Override
public void run(){
if (countdown()) {
if(minutes < 9 && seconds < 9)
timerOutput.setText("0"+minutes + ": 0" + seconds);
else if(minutes < 9)
timerOutput.setText("0"+minutes + ":" + seconds);
else if(seconds < 9)
timerOutput.setText(minutes + ": 0" + seconds);
}
else
{
System.out.println("Finish!");
timerOutput.setText("Time is up!");
timer.cancel();
startBut.setEnabled(true);
}
}
};
private boolean countdown(){
seconds --;
if (seconds < 0){
minutes--;
seconds = 59;
if (minutes == -1){
return false;
}
}
return true;
}
Well TimerTasks aren't designed to be reused. The best you can do is create a new TimerTask every time you're going to reschedule it.
Although you can't simply restart a Timer, you could create a Timer wrapper class which would act exactly like a Timer but allow a simple restart method that would instantiate a new Timer in the background. For example;
public class RestartableTimer{
private Timer timer;
private long delay, period;
public RestartableTimer(){
timer = new Timer();
}
public void scheduleAtFixedRate(TimerTask task, long delay, long period){
this.delay = delay;
this.period = period;
timer.scheduleAtFixedRate(task, delay, period);
}
public void restart(TimerTask task){
timer.cancel();
timer = new Timer();
timer.scheduleAtFixedRate(task, delay, period);
}
}
A fair warning, this would not allow for polymorphism. You couldn't for example store a RestartableTimer in a Timer reference. You will also still need to instantiate a new TimerTask when you restart. If you wanted (and you knew you would only be reusing the same TimerTask), you could declare a custom and private embedded class in the above and let the wrapper class handle the creation of the new TimerTask. Alternatively you could have the class methods take a TimerTaskFactory which would implement an Interface which required a method that returned a TimerTask.
Below, an example of using the above class;
public static void main(String[] args) throws InterruptedException{
TimerTask task = new TimerTask(){
#Override
public void run() {
System.out.println("Running");
}};
RestartableTimer rt = new RestartableTimer();
System.out.println("Timer starting with one task");
rt.scheduleAtFixedRate(task, 1000, 1000);
Thread.sleep(5000);
System.out.println("Timer restarting with another task");
rt.restart(new TimerTask(){
int count = 0;
#Override
public void run() {
if(count>4) {
System.out.println("Done");
this.cancel();
} else {
System.out.println("Running 2");
count++;
}
}});
}

Associating timer with tables

I am new to timer's and don't know much about them .My problem is i am creating 2 tables dynamically, and when ever a table is create a timer for 10 mins is assigned to it. I.e. the user has to fill that table in 10 mins else the table will be destroyed. I tried a making a small demo in which i print stuff
The code is :
final Timer mytimers = new Timer();
Timer mytimers1 = new Timer();
mytimers1 = new Timer();
final long delay1 = 5*1000;
// mytimers = new Timer();
mytimers.schedule(new TimerTask() {
Long current1 = System.currentTimeMillis();
long check = current1;
#Override
public void run() {
Long current = System.currentTimeMillis();
System.out.println(current);
System.out.println("\n");
if((current1 + delay1)<current)
{
System.out.println("mytimmer is about to stop");
mytimers.cancel();
}
}
}, 100, 1000);
mytimers1.schedule(new TimerTask() {
#Override
public void run() {
Long current = System.currentTimeMillis();
System.out.println("in" + current);
}
}, delay1, 1000);
}
but when i tried implementing this int he final project it does not work as i have to make any variable inside the run a final , thus its value can not to be changed !!!
Please let what should i do !!Thank you
i have to make any variable inside the run a final , thus its value can not to be changed!
Either turn these variables into member variables or encapsulate these values in a proper class, instantiate the class and give a reference to that object to the timer task.
Even though the reference is final, the timer task will still be able to do things such as myTableController.destroyTable().
do it like this :
class YourClass{
Timer mytimers = new Timer();
Timer mytimers1 = new Timer();
long delay1 = 5*1000;
mytimers.schedule(new TimerTask() {
Long current1 = System.currentTimeMillis();
long check = current1;
#Override
public void run() {
Long current = System.currentTimeMillis();
System.out.println(current);
System.out.println("\n");
if((current1 + delay1)<current) {
System.out.println("mytimmer is about to stop");
mytimers.cancel();
}
}
}, 100, 1000);
mytimers1.schedule(new TimerTask() {
#Override
public void run() {
Long current = System.currentTimeMillis();
System.out.println("in" + current);
}
}, delay1, 1000);
}
in your case you have created anonymous 'concrete' class ie TimerTask, and you are trying to access variables which are not in its scope.
So, if the variables you are trying to access are local(method) variables then they should be declared final or the other way around is to declare those variables as instant(member) variables that what i have done above.

Pausing/stopping and starting/resuming Java TimerTask continuously?

I have one simple question regarding Java TimerTask. How do I pause/resume two TimerTask tasks based on a certain condition? For example I have two timers that run between each other. When a certain condition has been met inside the task of first timer, the first timer stops and starts the second timer, and the same thing happens when a certain condition has been met inside the task of second timer. The class below shows exactly what I mean:
public class TimerTest {
Timer timer1;
Timer timer2;
volatile boolean a = false;
public TimerTest() {
timer1 = new Timer();
timer2 = new Timer();
}
public void runStart() {
timer1.scheduleAtFixedRate(new Task1(), 0, 1000);
}
class Task1 extends TimerTask {
public void run() {
System.out.println("Checking a");
a = SomeClass.getSomeStaticValue();
if (a) {
// Pause/stop timer1, start/resume timer2 for 5 seconds
timer2.schedule(new Task2(), 5000);
}
}
}
class Task2 extends TimerTask{
public void run() {
System.out.println("Checking a");
a = SomeClass.getSomeStaticValue();
if (!a) {
// Pause/stop timer2, back to timer1
timer1.scheduleAtFixedRate(new Task1(), 0, 1000);
}
// Do something...
}
}
public static void main(String args[]) {
TimerTest tt = new TimerTest();
tt.runStart();
}
}
So my question is, how do I pause timer1 while running timer2 and vice versa while timer2 is running? Performance and timing is my main concern as this needs to be implemented inside another running thread. By the way I am trying to implement these concurrent timers on Android.
Thanks for your help!
From TimerTask.cancel():
Note that calling this method from
within the run method of a repeating
timer task absolutely guarantees that
the timer task will not run again.
So once cancelled, it won't ever run again. You'd be better off instead using the more modern ScheduledExecutorService (from Java 5+).
Edit: The basic construct is:
ScheduledExecutorService exec = Executors.newSingleThreadScheduledExecutor();
exec.scheduleAtFixedRate(runnable, 0, 1000, TimeUnit.MILLISECONDS);
but looking into it there's no way of cancelling that task once its started without shutting down the service, which is a bit odd.
TimerTask might be easier in this case but you'll need to create a new instance when you start one up. It can't be reused.
Alternatively you could encapsulate each task as a separate transient service:
final ScheduledExecutorService exec = Executors.newSingleThreadScheduledExecutor();
Runnable task1 = new Runnable() {
public void run() {
a++;
if (a == 3) {
exec.shutdown();
exec = Executors.newSingleThreadScheduledExecutor();
exec.scheduleAtFixedRate(task2, 0, 1000, TimeUnit.MILLISECONDS)
}
}
};
exec.scheduleAtFixedRate(task1, 0, 1000, TimeUnit.MILLISECONDS);
easiest solution i found: just add a boolean in the run code in the timer task, like so:
timer.schedule( new TimerTask() {
public void run() {
if(!paused){
//do your thing
}
}
}, 0, 1000 );
If you have already canceled one timer, you can't re-start it, you'll have to create a new one.
See this answer, it contains a video and the source code how I did something similar.
Basically there are two method: pause and resume
In pause:
public void pause() {
this.timer.cancel();
}
In resume:
public void resume() {
this.timer = new Timer();
this.timer.schedule( aTask, 0, 1000 );
}
That makes the perception of pause/resume.
If your timers perform different actions based on the state of the application you may consider use the StatePattern
Fist define a abstract state:
abstract class TaskState {
public void run();
public TaskState next();
}
And provide as many states as you like. The key is that one state leads you to another.
class InitialState extends TaskState {
public void run() {
System.out.println( "starting...");
}
public TaskState next() {
return new FinalState();
}
}
class FinalState extends TaskState {
public void run() {
System.out.println("Finishing...");
}
public TaskState next(){
return new InitialState();
}
}
And then you change the state in your timer.
Timer timer = new Timer();
TaskState state = new InitialState();
timer.schedule( new TimerTask() {
public void run() {
this.state.run();
if( shouldChangeState() ) {
this.state = this.state.next();
}
}
}, 0, 1000 );
Finally, if what you need is to perform the same thing, but at different rates, you may consider using the TimingFramework. It is a bit more complex but let's you do cool animations, by allowing the painting of certain component take place at different rates ( instead of being linear )
In my opinion, this is somewhat misguided. If your code needs time guarantees, you can't use Timer anyway, nor would you want to. "This class does not offer real-time guarantees: it schedules tasks using the Object.wait(long) method."
The answer, IMHO, is that you don't want to pause and restart your timers. You just want to suppress their run methods from doing their business. And that's easy: you just wrap them in an if statement. The switch is on, they run, the switch is off, they miss that cycle.
Edit: The question has shifted substantially from what it was originally, but I'll leave this answer in case it helps anyone. My point is: if you don't care when your event fires in the N millisecond span (just that it doesn't EXCEED once every N milliseconds), you can just use conditionals on the run methods. This is, in fact, a very common case, especially when N is less than 1 second.
Reviewing your source code, here are the changes ( which pretty much validate my previous answer )
In task1:
// Stop timer1 and start timer2
timer1.cancel();
timer2 = new Timer(); // <-- just insert this line
timer2.scheduleAtFixedRate(new Task2(), 0, 1000);
and in task2:
// Stop timer2 and start timer1
timer2.cancel();
timer1 = new Timer(); // <-- just insert this other
timer1.scheduleAtFixedRate(new Task1(), 0, 1000);
It runs on my machine:
Android won't reuse a TimerTask that has already been scheduled once. So it's necessary to reinstantiate both the Timer and TimerTask, for example like this in a Fragment:
private Timer timer;
private TimerTask timerTask;
public void onResume ()
{
super.onResume();
timer = new Timer();
timerTask = new MyTimerTask();
timer.schedule(timerTask, 0, 1000);
}
public void onPause ()
{
super.onPause();
timer.cancel(); // Renders Timer unusable for further schedule() calls.
}
I am able to stop a timer and a task using following code:
if(null != timer)
{
timer.cancel();
Log.i(LOG_TAG,"Number of cancelled tasks purged: " + timer.purge());
timer = null;
}
if(task != null)
{
Log.i(LOG_TAG,"Tracking cancellation status: " + task.cancel());
task = null;
}
Timer timer1;
private boolean videoCompleteCDR=false;
private boolean isVideoPlaying=false;
int videoTime=0;
private int DEFAULT_VIDEO_PLAY_TIME = 30;
#Override
public View onCreate(){
isVideoPlaying = true; //when server response is successfully
}
#Override
public void onPause() {
super.onPause();
if(isVideoPlaying ) {
if(this.timer1 !=null) {
this.timer1.cancel();
}
}
}
#Override
public void onResume() {
super.onResume();
if(isVideoPlaying && !videoCompleteCDR) {
callTimerTask();
}
}
#Override
public void onHiddenChanged(boolean hidden) {
super.onHiddenChanged(hidden);
if (!hidden) {
printLog( "GameFragment visible ");
if(isVideoPlaying && !videoCompleteCDR) {
callTimerTask();
}
} else {
printLog("GameFragment in visible ");
if(isVideoPlaying) {
if(this.timer1 !=null) {
this.timer1.cancel();
}
}
}
}
private void callTimerTask() {
// TODO Timer for auto sliding
printLog( "callTimerTask Start" );
timer1 = new Timer();
timer1.schedule(new TimerTask() {
#Override
public void run() {
if (getActivity() != null) {
getActivity().runOnUiThread(new Runnable() {
#Override
public void run() {
if (getActivity() == null) {
return;
}
videoTime++;
if(DEFAULT_VIDEO_PLAY_TIME ==videoTime){
videoCompleteCDR=true;
Log.e("KeshavTimer", "callTimerTask videoCompleteCDR called.... " +videoTime);
destroyTimer();
}
Log.e("KeshavTimer", "callTimerTask videoTime " +videoTime);
}
});
} else {
printLog("callTimerTask getActivity is null ");
}
}
}, 1000, 1000);
// TODO 300, 2000;
}
private void destroyTimer(){
this.timer1.cancel();
}

Categories