1 7 8 package java.util; 9 import java.util.Date ; 10 11 58 59 public class Timer { 60 66 private TaskQueue queue = new TaskQueue(); 67 68 71 private TimerThread thread = new TimerThread(queue); 72 73 80 private Object threadReaper = new Object () { 81 protected void finalize() throws Throwable { 82 synchronized(queue) { 83 thread.newTasksMayBeScheduled = false; 84 queue.notify(); } 86 } 87 }; 88 89 93 private static int nextSerialNumber = 0; 94 private static synchronized int serialNumber() { 95 return nextSerialNumber++; 96 } 97 98 105 public Timer() { 106 this("Timer-" + serialNumber()); 107 } 108 109 121 public Timer(boolean isDaemon) { 122 this("Timer-" + serialNumber(), isDaemon); 123 } 124 125 135 public Timer(String name) { 136 thread.setName(name); 137 thread.start(); 138 } 139 140 151 public Timer(String name, boolean isDaemon) { 152 thread.setName(name); 153 thread.setDaemon(isDaemon); 154 thread.start(); 155 } 156 157 167 public void schedule(TimerTask task, long delay) { 168 if (delay < 0) 169 throw new IllegalArgumentException ("Negative delay."); 170 sched(task, System.currentTimeMillis()+delay, 0); 171 } 172 173 183 public void schedule(TimerTask task, Date time) { 184 sched(task, time.getTime(), 0); 185 } 186 187 217 public void schedule(TimerTask task, long delay, long period) { 218 if (delay < 0) 219 throw new IllegalArgumentException ("Negative delay."); 220 if (period <= 0) 221 throw new IllegalArgumentException ("Non-positive period."); 222 sched(task, System.currentTimeMillis()+delay, -period); 223 } 224 225 254 public void schedule(TimerTask task, Date firstTime, long period) { 255 if (period <= 0) 256 throw new IllegalArgumentException ("Non-positive period."); 257 sched(task, firstTime.getTime(), -period); 258 } 259 260 291 public void scheduleAtFixedRate(TimerTask task, long delay, long period) { 292 if (delay < 0) 293 throw new IllegalArgumentException ("Negative delay."); 294 if (period <= 0) 295 throw new IllegalArgumentException ("Non-positive period."); 296 sched(task, System.currentTimeMillis()+delay, period); 297 } 298 299 329 public void scheduleAtFixedRate(TimerTask task, Date firstTime, 330 long period) { 331 if (period <= 0) 332 throw new IllegalArgumentException ("Non-positive period."); 333 sched(task, firstTime.getTime(), period); 334 } 335 336 348 private void sched(TimerTask task, long time, long period) { 349 if (time < 0) 350 throw new IllegalArgumentException ("Illegal execution time."); 351 352 synchronized(queue) { 353 if (!thread.newTasksMayBeScheduled) 354 throw new IllegalStateException ("Timer already cancelled."); 355 356 synchronized(task.lock) { 357 if (task.state != TimerTask.VIRGIN) 358 throw new IllegalStateException ( 359 "Task already scheduled or cancelled"); 360 task.nextExecutionTime = time; 361 task.period = period; 362 task.state = TimerTask.SCHEDULED; 363 } 364 365 queue.add(task); 366 if (queue.getMin() == task) 367 queue.notify(); 368 } 369 } 370 371 385 public void cancel() { 386 synchronized(queue) { 387 thread.newTasksMayBeScheduled = false; 388 queue.clear(); 389 queue.notify(); } 391 } 392 393 413 public int purge() { 414 int result = 0; 415 416 synchronized(queue) { 417 for (int i = queue.size(); i > 0; i--) { 418 if (queue.get(i).state == TimerTask.CANCELLED) { 419 queue.quickRemove(i); 420 result++; 421 } 422 } 423 424 if (result != 0) 425 queue.heapify(); 426 } 427 428 return result; 429 } 430 } 431 432 438 class TimerThread extends Thread { 439 446 boolean newTasksMayBeScheduled = true; 447 448 454 private TaskQueue queue; 455 456 TimerThread(TaskQueue queue) { 457 this.queue = queue; 458 } 459 460 public void run() { 461 try { 462 mainLoop(); 463 } finally { 464 synchronized(queue) { 466 newTasksMayBeScheduled = false; 467 queue.clear(); } 469 } 470 } 471 472 475 private void mainLoop() { 476 while (true) { 477 try { 478 TimerTask task; 479 boolean taskFired; 480 synchronized(queue) { 481 while (queue.isEmpty() && newTasksMayBeScheduled) 483 queue.wait(); 484 if (queue.isEmpty()) 485 break; 487 long currentTime, executionTime; 489 task = queue.getMin(); 490 synchronized(task.lock) { 491 if (task.state == TimerTask.CANCELLED) { 492 queue.removeMin(); 493 continue; } 495 currentTime = System.currentTimeMillis(); 496 executionTime = task.nextExecutionTime; 497 if (taskFired = (executionTime<=currentTime)) { 498 if (task.period == 0) { queue.removeMin(); 500 task.state = TimerTask.EXECUTED; 501 } else { queue.rescheduleMin( 503 task.period<0 ? currentTime - task.period 504 : executionTime + task.period); 505 } 506 } 507 } 508 if (!taskFired) queue.wait(executionTime - currentTime); 510 } 511 if (taskFired) task.run(); 513 } catch(InterruptedException e) { 514 } 515 } 516 } 517 } 518 519 526 class TaskQueue { 527 535 private TimerTask [] queue = new TimerTask [128]; 536 537 541 private int size = 0; 542 543 546 int size() { 547 return size; 548 } 549 550 553 void add(TimerTask task) { 554 if (++size == queue.length) { 556 TimerTask [] newQueue = new TimerTask [2*queue.length]; 557 System.arraycopy(queue, 0, newQueue, 0, size); 558 queue = newQueue; 559 } 560 561 queue[size] = task; 562 fixUp(size); 563 } 564 565 569 TimerTask getMin() { 570 return queue[1]; 571 } 572 573 578 TimerTask get(int i) { 579 return queue[i]; 580 } 581 582 585 void removeMin() { 586 queue[1] = queue[size]; 587 queue[size--] = null; fixDown(1); 589 } 590 591 596 void quickRemove(int i) { 597 assert i <= size; 598 599 queue[i] = queue[size]; 600 queue[size--] = null; } 602 603 607 void rescheduleMin(long newTime) { 608 queue[1].nextExecutionTime = newTime; 609 fixDown(1); 610 } 611 612 615 boolean isEmpty() { 616 return size==0; 617 } 618 619 622 void clear() { 623 for (int i=1; i<=size; i++) 625 queue[i] = null; 626 627 size = 0; 628 } 629 630 639 private void fixUp(int k) { 640 while (k > 1) { 641 int j = k >> 1; 642 if (queue[j].nextExecutionTime <= queue[k].nextExecutionTime) 643 break; 644 TimerTask tmp = queue[j]; queue[j] = queue[k]; queue[k] = tmp; 645 k = j; 646 } 647 } 648 649 659 private void fixDown(int k) { 660 int j; 661 while ((j = k << 1) <= size && j > 0) { 662 if (j < size && 663 queue[j].nextExecutionTime > queue[j+1].nextExecutionTime) 664 j++; if (queue[k].nextExecutionTime <= queue[j].nextExecutionTime) 666 break; 667 TimerTask tmp = queue[j]; queue[j] = queue[k]; queue[k] = tmp; 668 k = j; 669 } 670 } 671 672 676 void heapify() { 677 for (int i = size/2; i >= 1; i--) 678 fixDown(i); 679 } 680 } 681 | Popular Tags |