I know how to count down using Timer and Tasktimer but im not sure how to reset my timer let alone adding another interval for my pause section without just copying my written code and creating another object for just my pause section. I wanted to save my int secondsworkout in another int so that I got my number (in seconds) and just reuse it somehow (if even possible).
public class Intervall {
Scanner stdin = new Scanner(System.in);
int secondsWorkout = stdin.nextInt() + 1;
int cache = secondsWorkout - 1;
Timer timer = new Timer();
TimerTask task = new TimerTask() {
@Override
public void run() {
secondsWorkout--;
System.out.println(secondsWorkout + " seconds");
if(secondsWorkout == 0) {
timer.cancel();
System.out.println("DING!");
secondsWorkout = cache;
}
}
};
public void startWorkout() {
timer.scheduleAtFixedRate(task, 1000, 1000);
}
public static void main(String[] args){
System.out.println("Please enter a number");
Intervall kek = new Intervall();
kek.startWorkout();
}
}
You are using an anonymous inner class which accesses fields of its outer class:
int secondsWorkout = stdin.nextInt() + 1;
int cache = secondsWorkout - 1;
TimerTask task = new TimerTask() {
@Override
public void run() {
secondsWorkout--;
...
If you want to make it reusable, declare a real class with fields:
class WorkoutTimerTask extends TimerTask {
int secondsWorkout;
int cache;
WorkoutTimerTask(int secondsWorkout, int cache) {
this.secondsWorkout = secondsWorkout;
this.cache = cache;
}
@Override
public void run() {
secondsWorkout--;
System.out.println(secondsWorkout + " seconds");
if(secondsWorkout == 0) {
timer.cancel();
System.out.println("DING!");
secondsWorkout = cache;
}
}
};
And then create two instances of it, e.g.:
Scanner stdin = new Scanner(System.in);
int secondsWorkout = stdin.nextInt() + 1;
int secondsPause = stdin.nextInt() + 1;
Timer timer = new Timer();
WorkoutTimerTask workout = new WorkoutTimerTask(secondsWorkout, secondsWorkout - 1);
WorkoutTimerTask pause = new WorkoutTimerTask(secondsPause, secondsPause - 1);
...
Notes:
You can declare the class as an inner class (in the same java file) or in a separate file called 'WorkoutTimerTask.java'.
Instead of counting down a second on each scheduled execution, you could also keep track of the System.currentTimeMillis() value at the start, and compare it to the current time millis. It's probably more accurate and maybe more understandable:
public class WorkoutTimerTask extends TimerTask {
private final int maxSeconds;
private long startMillis;
public WorkoutTimerTask(int maxSeconds) {
this.maxSeconds = maxSeconds;
this.startMillis = System.currentTimeMillis();
}
@Override
public void run() {
long elapsedSeconds = (System.currentTimeMillis() - startMillis) / 1000;
if (elapsedSeconds < maxSeconds) {
System.out.printf("%s seconds%n", elapsedSeconds);
} else {
System.out.println("DING!");
cancel();
}
}
};
You can also cancel the timer via the TimerTask by calling cancel()
EDIT: Thinking about what you're trying to do, I think maybe you don't want to try and 'chain' these TimerTasks at all. Instead, just implement a smart TimerTask which knows about workout and pause phases, for example:
public class WorkoutTimer extends TimerTask {
private final int workoutSeconds;
private final int pauseSeconds;
private long startMillis;
private Phase phase;
// bonus feature: keep track of the number of workout/pause cycles
private int workoutCounter;
private enum Phase {
WORKOUT, PAUSE
}
public WorkoutTimer(int workoutSeconds, int pauseSeconds) {
this.workoutSeconds = workoutSeconds;
this.pauseSeconds = pauseSeconds;
}
@Override
public void run() {
if (phase == null) {
startNextPhase();
}
long elapsedSeconds = getElapsedSeconds();
long maxSeconds = getMaxSeconds();
if (elapsedSeconds < maxSeconds) {
// carriage return at the end allows 'printing in place'
System.out.printf("%s#%s %s seconds\r", phase, workoutCounter, elapsedSeconds + 1);
}
else {
System.out.printf("%s#%s finished%n", phase, workoutCounter);
startNextPhase();
}
}
private long getElapsedSeconds() {
return (System.currentTimeMillis() - startMillis) / 1000;
}
private long getMaxSeconds() {
if (phase == Phase.WORKOUT) {
return workoutSeconds;
}
else {
return pauseSeconds;
}
}
private void startNextPhase() {
if (phase == null || phase == Phase.PAUSE) {
phase = Phase.WORKOUT;
workoutCounter++;
}
else {
phase = Phase.PAUSE;
}
startMillis = System.currentTimeMillis();
}
public static void main(String[] args) {
Scanner stdin = new Scanner(System.in);
System.out.println("Please enter the number of workout seconds");
int workoutSeconds = stdin.nextInt();
System.out.println("Please enter the number of pause seconds");
int pauseSeconds = stdin.nextInt();
WorkoutTimer workoutTimer = new WorkoutTimer(workoutSeconds, pauseSeconds);
Timer timer = new Timer();
// 300 to make sure the timer doesn't seem laggy
timer.scheduleAtFixedRate(workoutTimer, 0, 300);
}
}