Skip to content

Instantly share code, notes, and snippets.

@iuridiniz
Last active August 26, 2025 11:25
Show Gist options
  • Select an option

  • Save iuridiniz/94ee78d844989bbeb1ce1d7a81e26e59 to your computer and use it in GitHub Desktop.

Select an option

Save iuridiniz/94ee78d844989bbeb1ce1d7a81e26e59 to your computer and use it in GitHub Desktop.
sync.Once (golang) in java
public class OnceExample {
public static void main(String[] args) {
testSimpleOnce();
testStatefulOnce();
}
private static void testSimpleOnce() {
SimpleOnce simpleOnce = new SimpleOnce();
System.out.println("Initial state: " + simpleOnce.getState()); // NOT_EXECUTED
try {
simpleOnce.doOnce(() -> System.out.println("Executed once!"));
System.out.println("After execution: " + simpleOnce.getState()); // COMPLETED
} catch (Exception e) {
e.printStackTrace();
}
}
private static void testStatefulOnce() {
StatefulOnce statefulOnce = new StatefulOnce();
System.out.println("Initial state: " + statefulOnce.getState()); // NOT_STARTED
// Simulate concurrent execution
Thread t1 = new Thread(() -> {
try {
statefulOnce.doOnce(() -> {
System.out.println("State during execution: " + statefulOnce.getState()); // RUNNING
try { Thread.sleep(1000); } catch (InterruptedException e) {}
System.out.println("Execution completed!");
});
} catch (Exception e) {
e.printStackTrace();
}
});
t1.start();
// Check state while running
try {
Thread.sleep(100);
System.out.println("State while running: " + statefulOnce.getState()); // RUNNING
t1.join();
System.out.println("Final state: " + statefulOnce.getState()); // COMPLETED
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
import java.util.concurrent.atomic.AtomicBoolean;
public class SimpleOnce {
public enum State { NOT_EXECUTED, COMPLETED }
private final AtomicBoolean done = new AtomicBoolean(false);
public void doOnce(Runnable action) throws Exception {
if (done.get()) {
return;
}
synchronized (this) {
if (done.get()) {
return;
}
try {
action.run();
done.set(true);
} catch (Exception e) {
throw e;
}
}
}
public State getState() {
return done.get() ? State.COMPLETED : State.NOT_EXECUTED;
}
public boolean isCompleted() {
return done.get();
}
}
import java.util.concurrent.atomic.AtomicReference;
public class StatefulOnce {
public enum State { NOT_STARTED, RUNNING, COMPLETED }
private final AtomicReference<State> state = new AtomicReference<>(State.NOT_STARTED);
private final Object lock = new Object();
public void doOnce(Runnable action) throws Exception {
if (state.get() == State.COMPLETED) {
return;
}
synchronized (lock) {
if (state.get() == State.COMPLETED) {
return;
}
if (state.get() == State.NOT_STARTED) {
state.set(State.RUNNING);
try {
action.run();
state.set(State.COMPLETED);
} catch (Exception e) {
state.set(State.NOT_STARTED);
throw e;
}
}
}
}
public State getState() {
return state.get();
}
public boolean isCompleted() {
return state.get() == State.COMPLETED;
}
public boolean isRunning() {
return state.get() == State.RUNNING;
}
public boolean isNotStarted() {
return state.get() == State.NOT_STARTED;
}
}
@iuridiniz
Copy link
Author

iuridiniz commented Aug 26, 2025

Key Differences

Feature SimpleOnce StatefulOnce
Implementation AtomicBoolean + synchronized AtomicReference + synchronized
States NOT_EXECUTED, COMPLETED NOT_STARTED, RUNNING, COMPLETED
State visibility Binary (done/not done) Full execution lifecycle
Memory overhead Lower (single boolean) Higher (enum reference)
API methods getState(), isCompleted() getState(), isCompleted(), isRunning(), isNotStarted()
Concurrent visibility Limited Full visibility during execution
Complexity Simpler More complex but more informative
Use case Basic once-only execution Scenarios needing execution state monitoring
Performance Slightly faster Slightly slower due to enum operations

Both implementations are exception-safe and allow retries after failures, but StatefulOnce provides better visibility into the execution state for concurrent scenarios.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment