import javax.swing.SwingWorker; import java.util.GregorianCalendar; import java.util.List; import java.util.concurrent.locks.ReentrantLock; /* * A SwingWorker class to call back GUIClock.update() on regural intervals */ public class ClockTimer extends SwingWorker { GUIClock clock = null; // the clock to call back int period = 1000; private final ReentrantLock lock = new ReentrantLock(); Thread thisWorker = null; public ClockTimer(GUIClock c, int callbackPeriod) { period = callbackPeriod; clock = c; } public synchronized void setPeriod(int newPeriod) { period = newPeriod; // interrupt the sleeping worker thread (if it has been started) if (thisWorker != null) thisWorker.interrupt(); } public void quit() { period = -1; // unlock if the lock was held by this thread try { lock.unlock(); } catch (Exception e) {}; // interrupt the sleeping worker thread if (thisWorker != null) thisWorker.interrupt(); } public synchronized int getPeriod() { return period; } /* * suspends calling update() */ public void suspend() { lock.lock(); } /* * resumed calling update() * must be called by the same thread than the suspend() */ public void resume() { if (lock.isHeldByCurrentThread()) lock.unlock(); } @Override public Void doInBackground() { // TODO replace sleep(period) with more accurate // version that tries to sleep up to the next period thisWorker = Thread.currentThread(); this.publish(new GregorianCalendar()); while (!isCancelled()) { try { Thread.sleep(getPeriod()); } catch (InterruptedException e) {} // ensure that we are not suspended lock.lock(); lock.unlock(); // negative period is used to mark quit if (period < 0) return null; // uncomment to see how suspend/resume works // System.out.println("ClockTimer:publish"); this.publish(new GregorianCalendar()); } return null; } // doInBackground() /* * process last time and update clock */ public void process(List times) { // take last in the list of accumulated times if (times.size() > 0) { GregorianCalendar t = times.get(times.size() - 1); clock.update(t); } } } // class ClockTimer