1package DesignPatterns.CreationalPatterns.SingletonDesignPattern.After;23import java.util.concurrent.atomic.AtomicInteger;45/**6 * Singleton: Ensures only one instance of JudgeAnalytics exists system-wide.7 * - Private constructor: no one can do "new JudgeAnalytics()".8 * - getInstance(): single point of access; creates the instance once, reuses it forever.9 * - Thread-safe: the static holder (JudgeAnalyticsHolder) is lazily loaded by the JVM.10 *11 * A singleton is shared by every thread, so its state must be thread-safe too.12 * "run++" is read-modify-write, so two threads can both read the same value and13 * one increment is lost. AtomicInteger does the whole step as one operation.14 */15public class JudgeAnalytics {1617 private final AtomicInteger run = new AtomicInteger(0);18 private final AtomicInteger submit = new AtomicInteger(0);1920 private JudgeAnalytics() {21 // Prevent instantiation from outside.22 }2324 public void countRun() {25 run.incrementAndGet();26 }2728 public void countSubmit() {29 submit.incrementAndGet();30 }3132 public int getRunCount() {33 return run.get();34 }3536 public int getSubmitCount() {37 return submit.get();38 }3940 /**41 * Single point of access. The instance is created lazily when first requested42 * and is thread-safe due to the class-loading semantics of the JVM.43 */44 public static JudgeAnalytics getInstance() {45 return JudgeAnalyticsHolder.INSTANCE;46 }4748 private static class JudgeAnalyticsHolder {4950 private static final JudgeAnalytics INSTANCE = new JudgeAnalytics();51 }52}53
1package DesignPatterns.CreationalPatterns.SingletonDesignPattern.After;23/**4 * All code uses JudgeAnalytics.getInstance(). There is only one instance;5 * run and submit counts are shared globally.6 */7class Main {89 public static void main(String[] args) {10 JudgeAnalytics analytics = JudgeAnalytics.getInstance();1112 analytics.countRun();13 analytics.countRun();14 analytics.countSubmit();1516 // Same instance can be obtained anywhere; counts are global.17 JudgeAnalytics same = JudgeAnalytics.getInstance();18 System.out.println("Total runs: " + same.getRunCount()); // 219 System.out.println("Total submits: " + same.getSubmitCount()); // 120 }21}22