Pomodoro Timer TUI in Java
This is a complete, runnable Pomodoro timer in one Java file.
Quick Run (from repo root)
1cd Site/static/code/examples/java
2javac PomodoroTimer.java
3java PomodoroTimerIt supports:
- configurable focus and break lengths
- start, pause, resume, and reset
- completed session counter
- terminal bell on phase transitions
Code (Single Public Class)
1import java.util.Locale;
2import java.util.Scanner;
3
4public class PomodoroTimer {
5 public static void main(String[] args) {
6 Scanner scanner = new Scanner(System.in);
7
8 System.out.print("Focus minutes (default 25): ");
9 int focusMinutes = parsePositiveInt(scanner.nextLine(), 25);
10 System.out.print("Break minutes (default 5): ");
11 int breakMinutes = parsePositiveInt(scanner.nextLine(), 5);
12
13 TimerState state = new TimerState(
14 focusMinutes * 60,
15 breakMinutes * 60
16 );
17
18 System.out.println(
19 "Commands: start, pause, resume, reset, status, quit"
20 );
21
22 while (true) {
23 if (state.running) {
24 sleepMs(1000);
25 state.tick();
26 System.out.println(state.statusLine());
27 } else {
28 System.out.print("> ");
29 String command = scanner.nextLine().trim().toLowerCase(
30 Locale.ROOT
31 );
32 if (handleCommand(command, state)) {
33 break;
34 }
35 }
36 }
37 }
38
39 private static boolean handleCommand(String command, TimerState state) {
40 switch (command) {
41 case "start":
42 case "resume":
43 state.running = true;
44 System.out.println("Timer running.");
45 return false;
46 case "pause":
47 state.running = false;
48 System.out.println("Timer paused.");
49 return false;
50 case "reset":
51 state.resetCurrentPhase();
52 state.running = false;
53 System.out.println("Current phase reset.");
54 return false;
55 case "status":
56 System.out.println(state.statusLine());
57 return false;
58 case "quit":
59 System.out.println("Good work today.");
60 return true;
61 default:
62 System.out.println(
63 "Unknown command. Use start, pause, resume, " +
64 "reset, status, quit"
65 );
66 return false;
67 }
68 }
69
70 private static int parsePositiveInt(String value, int fallback) {
71 try {
72 int parsed = Integer.parseInt(value.trim());
73 return parsed > 0 ? parsed : fallback;
74 } catch (NumberFormatException e) {
75 return fallback;
76 }
77 }
78
79 private static void sleepMs(long ms) {
80 try {
81 Thread.sleep(ms);
82 } catch (InterruptedException e) {
83 Thread.currentThread().interrupt();
84 }
85 }
86
87 private static class TimerState {
88 private final int focusSeconds;
89 private final int breakSeconds;
90 private int remainingSeconds;
91 private boolean focusPhase = true;
92 private int completedFocusSessions = 0;
93 private boolean running = false;
94
95 private TimerState(int focusSeconds, int breakSeconds) {
96 this.focusSeconds = focusSeconds;
97 this.breakSeconds = breakSeconds;
98 this.remainingSeconds = focusSeconds;
99 }
100
101 private void tick() {
102 remainingSeconds--;
103 if (remainingSeconds > 0) {
104 return;
105 }
106
107 if (focusPhase) {
108 completedFocusSessions++;
109 }
110
111 focusPhase = !focusPhase;
112 remainingSeconds = focusPhase ? focusSeconds : breakSeconds;
113 System.out.print("\u0007");
114 System.out.println(
115 focusPhase
116 ? "Break complete. Focus time."
117 : "Focus complete. Break time."
118 );
119 }
120
121 private String statusLine() {
122 int safeSeconds = Math.max(0, remainingSeconds);
123 int minutes = safeSeconds / 60;
124 int seconds = safeSeconds % 60;
125 String phase = focusPhase ? "FOCUS" : "BREAK";
126 String state = running ? "RUNNING" : "PAUSED";
127 return String.format(
128 "%s %02d:%02d | sessions=%d | %s",
129 phase,
130 minutes,
131 seconds,
132 completedFocusSessions,
133 state
134 );
135 }
136
137 private void resetCurrentPhase() {
138 remainingSeconds = focusPhase ? focusSeconds : breakSeconds;
139 }
140 }
141}Run It
1javac PomodoroTimer.java
2java PomodoroTimerWhy this works for beginners
- One public class keeps the file approachable.
- Nested
TimerStateseparates timing logic from command input. - The loop is predictable: read command or tick one second.