0

If I schedule an event sometime after the program starts, it won't say that its anticipating an event UNLESS I uncomment the code on line 11 (else System.out.println("[" + now() + "ms] In statis...")). What is going on with the thread?

public class Scheduler extends Thread {

    private final Queue<ScheduledEvent> actions = new LinkedList<>();
    private boolean running = true;
    @Override
    public void run() {
        while (running) {
            ScheduledEvent nextEvent = actions.peek();
            if (nextEvent != null) {
                System.out.println("[" + now() + "ms] Anticipating event at: " + nextEvent.time + "ms");
            } //else System.out.println("[" + now() + "ms] In statis...");

            if (nextEvent != null && nextEvent.time <= now())
                actions.poll().execute();
        }
    }

    private long now() {
        return System.currentTimeMillis();
    }

    public ScheduledEvent schedule(long delay, Runnable action) {
        return schedule(ScheduledEvent.delayedEvent(delay, action));
    }

    public ScheduledEvent scheduleAt(long time, Runnable action) {
        return schedule(ScheduledEvent.absoluteEvent(time, action));
    }

    public ScheduledEvent schedule(ScheduledEvent event) {
        System.out.println("Scheduled event at: " + event.time);
        actions.add(event);
        return event;
    }

    public void unschedule(ScheduledEvent event) {
        actions.remove(event);
    }

    public void quit() {
        running = false;
    }
    
}

I wrote a class to schedule events and run them after/at a given time (in milliseconds). If I schedule an event right as the program starts, it will continue to run and eventually execute the scheduled event. I added System.out.println("exiting!"); to the end of the run() function but it never outputs exiting!.

After some digging, I found this issue which seemed to fix the issue. However, I don't understand why this is happening and why where(!this.isInterrupted()) fixed the issue.

  • 2
    In a nutshell: your code isn't thread-safe (you're not using thread safe collections, or synchronizing/locking), so it's an "all bets are off" type thing. But, `System.out.println` _is_ synchronized, which can often "bring in" a lot of things from one thread to another. It's not guaranteed behavior by any means, but it can have effects like what you're seeing. A full tutorial on how to write thread-safe code is unfortunately out of scope for what this site is suited for, but I highly recommend finding one and reading it through. Multi-threading is very hard to learn piecemeal. – yshavit Oct 31 '22 at 02:13
  • Related: https://stackoverflow.com/q/25425130/217324 – Nathan Hughes Oct 31 '22 at 02:47
  • What is `ScheduledEvent`? – Basil Bourque Oct 31 '22 at 03:09
  • You seem to be needlessly reinventing [`ScheduledExecutorService`](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/concurrent/ScheduledExecutorService.html). – Basil Bourque Oct 31 '22 at 03:12
  • By the way, check out *java.time* for your time-keeping. – Basil Bourque Oct 31 '22 at 03:12

0 Answers0