/* * Schedule a task. */ private void scheduleImpl(TimerTask task, long delay, long period, boolean fixed) { synchronized (impl) { if (impl.cancelled) { throw new IllegalStateException("luni.41"); // $NON-NLS-1$ } long when = delay + System.currentTimeMillis(); if (when < 0) { throw new IllegalArgumentException("luni.42"); // $NON-NLS-1$ } synchronized (task.lock) { if (task.isScheduled()) { throw new IllegalStateException("luni.43"); // $NON-NLS-1$ } if (task.cancelled) { throw new IllegalStateException("luni.44"); // $NON-NLS-1$ } task.when = when; task.period = period; task.fixedRate = fixed; } // insert the newTask into queue impl.insertTask(task); } }
/** This method will be launched on separate thread for each Timer object. */ @Override public void run() { while (true) { final TimerTask task; synchronized (this) { // need to check cancelled inside the synchronized block if (cancelled) { return; } if (tasks.isEmpty()) { if (finished) { return; } // no tasks scheduled -- sleep until any task appear try { this.wait(); } catch (InterruptedException ignored) { } continue; } long currentTime = System.currentTimeMillis(); task = tasks.minimum(); long timeToSleep; synchronized (task.lock) { if (task.cancelled) { tasks.delete(0); continue; } // check the time to sleep for the first task scheduled timeToSleep = task.when - currentTime; } if (timeToSleep > 0) { // sleep! try { this.wait(timeToSleep); } catch (InterruptedException ignored) { } continue; } // no sleep is necessary before launching the task synchronized (task.lock) { int pos = 0; if (tasks.minimum().when != task.when) { pos = tasks.getTask(task); } if (task.cancelled) { tasks.delete(tasks.getTask(task)); continue; } // set time to schedule task.setScheduledTime(task.when); // remove task from queue tasks.delete(pos); // set when the next task should be launched if (task.period >= 0) { // this is a repeating task, if (task.fixedRate) { // task is scheduled at fixed rate task.when = task.when + task.period; } else { // task is scheduled at fixed delay task.when = System.currentTimeMillis() + task.period; } // insert this task into queue insertTask(task); } else { task.when = 0; } } } boolean taskCompletedNormally = false; try { task.run(); taskCompletedNormally = true; } finally { if (!taskCompletedNormally) { synchronized (this) { cancelled = true; } } } } }