Override Annotationhtml
1 package java.lang; 2 import java.lang.annotation.ElementType; 3 import java.lang.annotation.Retention; 4 import java.lang.annotation.RetentionPolicy; 5 import java.lang.annotation.Target; 6 7 /** 8 * Annotation type used to mark methods that override a method declaration in a 9 * superclass. Compilers produce an error if a method annotated with @Override 10 * does not actually override a method in a superclass. 11 * 12 * @since 1.5 13 */ 14 @Target(ElementType.METHOD) 15 @Retention(RetentionPolicy.SOURCE) 16 public @interface Override { 17 }
Runnable Interfacejava
1 package java.lang; 2 /** 3 * Represents a command that can be executed. Often used to run code in a 4 * different {@link Thread}. 5 */ 6 public interface Runnable { 7 public void run(); 8 }
Thread Classredis
1 package java.lang; 2 import dalvik.system.VMStack; 3 import java.util.ArrayList; 4 import java.util.HashMap; 5 import java.util.List; 6 import java.util.Map; 7 import libcore.util.EmptyArray; 8 9 /** 10 * A {@code Thread} is a concurrent unit of execution. It has its own call stack 11 * for methods being invoked, their arguments and local variables. Each virtual 12 * machine instance has at least one main {@code Thread} running when it is 13 * started; typically, there are several others for housekeeping. The 14 * application might decide to launch additional {@code Thread}s for specific 15 * purposes. 16 * <p> 17 * {@code Thread}s in the same VM interact and synchronize by the use of shared 18 * objects and monitors associated with these objects. Synchronized methods and 19 * part of the API in {@link Object} also allow {@code Thread}s to cooperate. 20 * <p> 21 * There are basically two main ways of having a {@code Thread} execute 22 * application code. One is providing a new class that extends {@code Thread} 23 * and overriding its {@link #run()} method. The other is providing a new 24 * {@code Thread} instance with a {@link Runnable} object during its creation. 25 * In both cases, the {@link #start()} method must be called to actually execute 26 * the new {@code Thread}. 27 * <p> 28 * Each {@code Thread} has an integer priority that basically determines the 29 * amount of CPU time the {@code Thread} gets. It can be set using the 30 * {@link #setPriority(int)} method. A {@code Thread} can also be made a daemon, 31 * which makes it run in the background. The latter also affects VM termination 32 * behavior: the VM does not terminate automatically as long as there are 33 * non-daemon threads running. 34 * 35 * @see java.lang.Object 36 * @see java.lang.ThreadGroup 37 * 38 */ 39 public class Thread implements Runnable { 40 private static final int NANOS_PER_MILLI = 1000000; 41 42 /** Park states */ 43 private static class ParkState { 44 /** park state indicating unparked */ 45 private static final int UNPARKED = 1; 46 /** park state indicating preemptively unparked */ 47 private static final int PREEMPTIVELY_UNPARKED = 2; 48 /** park state indicating parked */ 49 private static final int PARKED = 3; 50 } 51 /** 52 * A representation of a thread's state. A given thread may only be in one 53 * state at a time. 54 */ 55 public enum State { 56 /** 57 * The thread has been created, but has never been started. 58 */ 59 NEW, 60 /** 61 * The thread may be run. 62 */ 63 RUNNABLE, 64 /** 65 * The thread is blocked and waiting for a lock. 66 */ 67 BLOCKED, 68 /** 69 * The thread is waiting. 70 */ 71 WAITING, 72 /** 73 * The thread is waiting for a specified amount of time. 74 */ 75 TIMED_WAITING, 76 /** 77 * The thread has been terminated. 78 */ 79 TERMINATED 80 } 81 /** 82 * The maximum priority value allowed for a thread. 83 */ 84 public static final int MAX_PRIORITY = 10; 85 /** 86 * The minimum priority value allowed for a thread. 87 */ 88 public static final int MIN_PRIORITY = 1; 89 /** 90 * The normal (default) priority value assigned to threads. 91 */ 92 public static final int NORM_PRIORITY = 5; 93 /* some of these are accessed directly by the VM; do not rename them */ 94 volatile VMThread vmThread; 95 volatile ThreadGroup group; 96 volatile boolean daemon; 97 volatile String name; 98 volatile int priority; 99 volatile long stackSize; 100 Runnable target; 101 private static int count = 0; 102 /** 103 * Holds the thread's ID. We simply count upwards, so 104 * each Thread has a unique ID. 105 */ 106 private long id; 107 /** 108 * Normal thread local values. 109 */ 110 ThreadLocal.Values localValues; 111 /** 112 * Inheritable thread local values. 113 */ 114 ThreadLocal.Values inheritableValues; 115 /** Callbacks to run on interruption. */ 116 private final List<Runnable> interruptActions = new ArrayList<Runnable>(); 117 /** 118 * Holds the class loader for this Thread, in case there is one. 119 */ 120 private ClassLoader contextClassLoader; 121 /** 122 * Holds the handler for uncaught exceptions in this Thread, 123 * in case there is one. 124 */ 125 private UncaughtExceptionHandler uncaughtHandler; 126 /** 127 * Holds the default handler for uncaught exceptions, in case there is one. 128 */ 129 private static UncaughtExceptionHandler defaultUncaughtHandler; 130 /** 131 * Reflects whether this Thread has already been started. A Thread 132 * can only be started once (no recycling). Also, we need it to deduce 133 * the proper Thread status. 134 */ 135 boolean hasBeenStarted = false; 136 137 /** the park state of the thread */ 138 private int parkState = ParkState.UNPARKED; 139 140 /** The synchronization object responsible for this thread parking. */ 141 private Object parkBlocker; 142 143 /** 144 * Constructs a new {@code Thread} with no {@code Runnable} object and a 145 * newly generated name. The new {@code Thread} will belong to the same 146 * {@code ThreadGroup} as the {@code Thread} calling this constructor. 147 * 148 * @see java.lang.ThreadGroup 149 * @see java.lang.Runnable 150 */ 151 public Thread() { 152 create(null, null, null, 0); 153 } 154 /** 155 * Constructs a new {@code Thread} with a {@code Runnable} object and a 156 * newly generated name. The new {@code Thread} will belong to the same 157 * {@code ThreadGroup} as the {@code Thread} calling this constructor. 158 * 159 * @param runnable 160 * a {@code Runnable} whose method <code>run</code> will be 161 * executed by the new {@code Thread} 162 * 163 * @see java.lang.ThreadGroup 164 * @see java.lang.Runnable 165 */ 166 public Thread(Runnable runnable) { 167 create(null, runnable, null, 0); 168 } 169 170 /** 171 * Constructs a new {@code Thread} with a {@code Runnable} object and name 172 * provided. The new {@code Thread} will belong to the same {@code 173 * ThreadGroup} as the {@code Thread} calling this constructor. 174 * 175 * @param runnable 176 * a {@code Runnable} whose method <code>run</code> will be 177 * executed by the new {@code Thread} 178 * @param threadName 179 * the name for the {@code Thread} being created 180 * 181 * @see java.lang.ThreadGroup 182 * @see java.lang.Runnable 183 */ 184 public Thread(Runnable runnable, String threadName) { 185 if (threadName == null) { 186 throw new NullPointerException(); 187 } 188 189 create(null, runnable, threadName, 0); 190 } 191 192 /** 193 * Constructs a new {@code Thread} with no {@code Runnable} object and the 194 * name provided. The new {@code Thread} will belong to the same {@code 195 * ThreadGroup} as the {@code Thread} calling this constructor. 196 * 197 * @param threadName 198 * the name for the {@code Thread} being created 199 * 200 * @see java.lang.ThreadGroup 201 * @see java.lang.Runnable 202 * 203 */ 204 public Thread(String threadName) { 205 if (threadName == null) { 206 throw new NullPointerException(); 207 } 208 209 create(null, null, threadName, 0); 210 } 211 212 /** 213 * Constructs a new {@code Thread} with a {@code Runnable} object and a 214 * newly generated name. The new {@code Thread} will belong to the {@code 215 * ThreadGroup} passed as parameter. 216 * 217 * @param group 218 * {@code ThreadGroup} to which the new {@code Thread} will 219 * belong 220 * @param runnable 221 * a {@code Runnable} whose method <code>run</code> will be 222 * executed by the new {@code Thread} 223 * @throws IllegalThreadStateException 224 * if <code>group.destroy()</code> has already been done 225 * @see java.lang.ThreadGroup 226 * @see java.lang.Runnable 227 */ 228 public Thread(ThreadGroup group, Runnable runnable) { 229 create(group, runnable, null, 0); 230 } 231 232 /** 233 * Constructs a new {@code Thread} with a {@code Runnable} object, the given 234 * name and belonging to the {@code ThreadGroup} passed as parameter. 235 * 236 * @param group 237 * ThreadGroup to which the new {@code Thread} will belong 238 * @param runnable 239 * a {@code Runnable} whose method <code>run</code> will be 240 * executed by the new {@code Thread} 241 * @param threadName 242 * the name for the {@code Thread} being created 243 * @throws IllegalThreadStateException 244 * if <code>group.destroy()</code> has already been done 245 * @see java.lang.ThreadGroup 246 * @see java.lang.Runnable 247 */ 248 public Thread(ThreadGroup group, Runnable runnable, String threadName) { 249 if (threadName == null) { 250 throw new NullPointerException(); 251 } 252 253 create(group, runnable, threadName, 0); 254 } 255 256 /** 257 * Constructs a new {@code Thread} with no {@code Runnable} object, the 258 * given name and belonging to the {@code ThreadGroup} passed as parameter. 259 * 260 * @param group 261 * {@code ThreadGroup} to which the new {@code Thread} will belong 262 * @param threadName 263 * the name for the {@code Thread} being created 264 * @throws IllegalThreadStateException 265 * if <code>group.destroy()</code> has already been done 266 * @see java.lang.ThreadGroup 267 * @see java.lang.Runnable 268 */ 269 public Thread(ThreadGroup group, String threadName) { 270 if (threadName == null) { 271 throw new NullPointerException(); 272 } 273 274 create(group, null, threadName, 0); 275 } 276 277 /** 278 * Constructs a new {@code Thread} with a {@code Runnable} object, the given 279 * name and belonging to the {@code ThreadGroup} passed as parameter. 280 * 281 * @param group 282 * {@code ThreadGroup} to which the new {@code Thread} will 283 * belong 284 * @param runnable 285 * a {@code Runnable} whose method <code>run</code> will be 286 * executed by the new {@code Thread} 287 * @param threadName 288 * the name for the {@code Thread} being created 289 * @param stackSize 290 * a stack size for the new {@code Thread}. This has a highly 291 * platform-dependent interpretation. It may even be ignored 292 * completely. 293 * @throws IllegalThreadStateException 294 * if <code>group.destroy()</code> has already been done 295 * @see java.lang.ThreadGroup 296 * @see java.lang.Runnable 297 */ 298 public Thread(ThreadGroup group, Runnable runnable, String threadName, long stackSize) { 299 if (threadName == null) { 300 throw new NullPointerException(); 301 } 302 create(group, runnable, threadName, stackSize); 303 } 304 305 /** 306 * Package-scope method invoked by Dalvik VM to create "internal" 307 * threads or attach threads created externally. 308 * 309 * Don't call Thread.currentThread(), since there may not be such 310 * a thing (e.g. for Main). 311 */ 312 Thread(ThreadGroup group, String name, int priority, boolean daemon) { 313 synchronized (Thread.class) { 314 id = ++Thread.count; 315 } 316 317 if (name == null) { 318 this.name = "Thread-" + id; 319 } else { 320 this.name = name; 321 } 322 323 if (group == null) { 324 throw new InternalError("group not specified"); 325 } 326 327 this.group = group; 328 329 this.target = null; 330 this.stackSize = 0; 331 this.priority = priority; 332 this.daemon = daemon; 333 334 /* add ourselves to our ThreadGroup of choice */ 335 this.group.addThread(this); 336 } 337 338 /** 339 * Initializes a new, existing Thread object with a runnable object, 340 * the given name and belonging to the ThreadGroup passed as parameter. 341 * This is the method that the several public constructors delegate their 342 * work to. 343 * 344 * @param group ThreadGroup to which the new Thread will belong 345 * @param runnable a java.lang.Runnable whose method <code>run</code> will 346 * be executed by the new Thread 347 * @param threadName Name for the Thread being created 348 * @param stackSize Platform dependent stack size 349 * @throws IllegalThreadStateException if <code>group.destroy()</code> has 350 * already been done 351 * @see java.lang.ThreadGroup 352 * @see java.lang.Runnable 353 */ 354 private void create(ThreadGroup group, Runnable runnable, String threadName, long stackSize) { 355 Thread currentThread = Thread.currentThread(); 356 if (group == null) { 357 group = currentThread.getThreadGroup(); 358 } 359 360 if (group.isDestroyed()) { 361 throw new IllegalThreadStateException("Group already destroyed"); 362 } 363 364 this.group = group; 365 366 synchronized (Thread.class) { 367 id = ++Thread.count; 368 } 369 370 if (threadName == null) { 371 this.name = "Thread-" + id; 372 } else { 373 this.name = threadName; 374 } 375 376 this.target = runnable; 377 this.stackSize = stackSize; 378 379 this.priority = currentThread.getPriority(); 380 381 this.contextClassLoader = currentThread.contextClassLoader; 382 383 // Transfer over InheritableThreadLocals. 384 if (currentThread.inheritableValues != null) { 385 inheritableValues = new ThreadLocal.Values(currentThread.inheritableValues); 386 } 387 388 // add ourselves to our ThreadGroup of choice 389 this.group.addThread(this); 390 } 391 392 /** 393 * Returns the number of active {@code Thread}s in the running {@code 394 * Thread}'s group and its subgroups. 395 * 396 * @return the number of {@code Thread}s 397 */ 398 public static int activeCount() { 399 return currentThread().getThreadGroup().activeCount(); 400 } 401 402 /** 403 * Does nothing. 404 */ 405 public final void checkAccess() { 406 } 407 408 /** 409 * Returns the number of stack frames in this thread. 410 * 411 * @return Number of stack frames 412 * @deprecated The results of this call were never well defined. To make 413 * things worse, it would depend on whether the Thread was 414 * suspended or not, and suspend was deprecated too. 415 */ 416 @Deprecated 417 public int countStackFrames() { 418 return getStackTrace().length; 419 } 420 421 /** 422 * Returns the Thread of the caller, that is, the current Thread. 423 * 424 * @return the current Thread. 425 */ 426 public static Thread currentThread() { 427 return VMThread.currentThread(); 428 } 429 430 /** 431 * Destroys the receiver without any monitor cleanup. 432 * 433 * @deprecated Not implemented. 434 */ 435 @Deprecated 436 public void destroy() { 437 throw new NoSuchMethodError("Thread.destroy()"); // TODO Externalize??? 438 } 439 440 /** 441 * Prints to the standard error stream a text representation of the current 442 * stack for this Thread. 443 * 444 * @see Throwable#printStackTrace() 445 */ 446 public static void dumpStack() { 447 new Throwable("stack dump").printStackTrace(); 448 } 449 450 /** 451 * Copies an array with all Threads which are in the same ThreadGroup as the 452 * receiver - and subgroups - into the array <code>threads</code> passed as 453 * parameter. If the array passed as parameter is too small no exception is 454 * thrown - the extra elements are simply not copied. 455 * 456 * @param threads 457 * array into which the Threads will be copied 458 * @return How many Threads were copied over 459 */ 460 public static int enumerate(Thread[] threads) { 461 Thread thread = Thread.currentThread(); 462 return thread.getThreadGroup().enumerate(threads); 463 } 464 465 /** 466 * Returns a map of all the currently live threads to their stack traces. 467 */ 468 public static Map<Thread, StackTraceElement[]> getAllStackTraces() { 469 Map<Thread, StackTraceElement[]> map = new HashMap<Thread, StackTraceElement[]>(); 470 471 // Find out how many live threads we have. Allocate a bit more 472 // space than needed, in case new ones are just being created. 473 int count = ThreadGroup.mSystem.activeCount(); 474 Thread[] threads = new Thread[count + count / 2]; 475 476 // Enumerate the threads and collect the stacktraces. 477 count = ThreadGroup.mSystem.enumerate(threads); 478 for (int i = 0; i < count; i++) { 479 map.put(threads[i], threads[i].getStackTrace()); 480 } 481 482 return map; 483 } 484 485 /** 486 * Returns the context ClassLoader for this Thread. 487 * 488 * @return ClassLoader The context ClassLoader 489 * @see java.lang.ClassLoader 490 * @see #getContextClassLoader() 491 */ 492 public ClassLoader getContextClassLoader() { 493 return contextClassLoader; 494 } 495 496 /** 497 * Returns the default exception handler that's executed when uncaught 498 * exception terminates a thread. 499 * 500 * @return an {@link UncaughtExceptionHandler} or <code>null</code> if 501 * none exists. 502 */ 503 public static UncaughtExceptionHandler getDefaultUncaughtExceptionHandler() { 504 return defaultUncaughtHandler; 505 } 506 507 /** 508 * Returns the thread's identifier. The ID is a positive <code>long</code> 509 * generated on thread creation, is unique to the thread, and doesn't change 510 * during the lifetime of the thread; the ID may be reused after the thread 511 * has been terminated. 512 * 513 * @return the thread's ID. 514 */ 515 public long getId() { 516 return id; 517 } 518 519 /** 520 * Returns the name of the Thread. 521 * 522 * @return the Thread's name 523 */ 524 public final String getName() { 525 return name; 526 } 527 528 /** 529 * Returns the priority of the Thread. 530 * 531 * @return the Thread's priority 532 * @see Thread#setPriority 533 */ 534 public final int getPriority() { 535 return priority; 536 } 537 538 /** 539 * Returns an array of {@link StackTraceElement} representing the current thread's stack. 540 */ 541 public StackTraceElement[] getStackTrace() { 542 StackTraceElement ste[] = VMStack.getThreadStackTrace(this); 543 return ste != null ? ste : EmptyArray.STACK_TRACE_ELEMENT; 544 } 545 546 /** 547 * Returns the current state of the Thread. This method is useful for 548 * monitoring purposes. 549 * 550 * @return a {@link State} value. 551 */ 552 public State getState() { 553 // TODO This is ugly and should be implemented better. 554 VMThread vmt = this.vmThread; 555 556 // Make sure we have a valid reference to an object. If native code 557 // deletes the reference we won't run into a null reference later. 558 VMThread thread = vmThread; 559 if (thread != null) { 560 // If the Thread Object became invalid or was not yet started, 561 // getStatus() will return -1. 562 int state = thread.getStatus(); 563 if(state != -1) { 564 return VMThread.STATE_MAP[state]; 565 } 566 } 567 return hasBeenStarted ? Thread.State.TERMINATED : Thread.State.NEW; 568 } 569 570 /** 571 * Returns the ThreadGroup to which this Thread belongs. 572 * 573 * @return the Thread's ThreadGroup 574 */ 575 public final ThreadGroup getThreadGroup() { 576 // TODO This should actually be done at native termination. 577 if (getState() == Thread.State.TERMINATED) { 578 return null; 579 } else { 580 return group; 581 } 582 } 583 584 /** 585 * Returns the thread's uncaught exception handler. If not explicitly set, 586 * then the ThreadGroup's handler is returned. If the thread is terminated, 587 * then <code>null</code> is returned. 588 * 589 * @return an {@link UncaughtExceptionHandler} instance or {@code null}. 590 */ 591 public UncaughtExceptionHandler getUncaughtExceptionHandler() { 592 if (uncaughtHandler != null) 593 return uncaughtHandler; 594 else 595 return group; // ThreadGroup is instance of UEH 596 } 597 598 /** 599 * Posts an interrupt request to this {@code Thread}. The behavior depends on 600 * the state of this {@code Thread}: 601 * <ul> 602 * <li> 603 * {@code Thread}s blocked in one of {@code Object}'s {@code wait()} methods 604 * or one of {@code Thread}'s {@code join()} or {@code sleep()} methods will 605 * be woken up, their interrupt status will be cleared, and they receive an 606 * {@link InterruptedException}. 607 * <li> 608 * {@code Thread}s blocked in an I/O operation of an 609 * {@link java.nio.channels.InterruptibleChannel} will have their interrupt 610 * status set and receive an 611 * {@link java.nio.channels.ClosedByInterruptException}. Also, the channel 612 * will be closed. 613 * <li> 614 * {@code Thread}s blocked in a {@link java.nio.channels.Selector} will have 615 * their interrupt status set and return immediately. They don't receive an 616 * exception in this case. 617 * <ul> 618 * 619 * @see Thread#interrupted 620 * @see Thread#isInterrupted 621 */ 622 public void interrupt() { 623 synchronized (interruptActions) { 624 for (int i = interruptActions.size() - 1; i >= 0; i--) { 625 interruptActions.get(i).run(); 626 } 627 } 628 629 VMThread vmt = this.vmThread; 630 if (vmt != null) { 631 vmt.interrupt(); 632 } 633 } 634 635 /** 636 * Returns a <code>boolean</code> indicating whether the current Thread ( 637 * <code>currentThread()</code>) has a pending interrupt request (<code> 638 * true</code>) or not (<code>false</code>). It also has the side-effect of 639 * clearing the flag. 640 * 641 * @return a <code>boolean</code> indicating the interrupt status 642 * @see Thread#currentThread 643 * @see Thread#interrupt 644 * @see Thread#isInterrupted 645 */ 646 public static boolean interrupted() { 647 return VMThread.interrupted(); 648 } 649 650 /** 651 * Returns <code>true</code> if the receiver has already been started and 652 * still runs code (hasn't died yet). Returns <code>false</code> either if 653 * the receiver hasn't been started yet or if it has already started and run 654 * to completion and died. 655 * 656 * @return a <code>boolean</code> indicating the liveness of the Thread 657 * @see Thread#start 658 */ 659 public final boolean isAlive() { 660 return (vmThread != null); 661 } 662 663 /** 664 * Returns a <code>boolean</code> indicating whether the receiver is a 665 * daemon Thread (<code>true</code>) or not (<code>false</code>) A 666 * daemon Thread only runs as long as there are non-daemon Threads running. 667 * When the last non-daemon Thread ends, the whole program ends no matter if 668 * it had daemon Threads still running or not. 669 * 670 * @return a <code>boolean</code> indicating whether the Thread is a daemon 671 * @see Thread#setDaemon 672 */ 673 public final boolean isDaemon() { 674 return daemon; 675 } 676 677 /** 678 * Returns a <code>boolean</code> indicating whether the receiver has a 679 * pending interrupt request (<code>true</code>) or not ( 680 * <code>false</code>) 681 * 682 * @return a <code>boolean</code> indicating the interrupt status 683 * @see Thread#interrupt 684 * @see Thread#interrupted 685 */ 686 public boolean isInterrupted() { 687 VMThread vmt = this.vmThread; 688 if (vmt != null) { 689 return vmt.isInterrupted(); 690 } 691 692 return false; 693 } 694 695 /** 696 * Blocks the current Thread (<code>Thread.currentThread()</code>) until 697 * the receiver finishes its execution and dies. 698 * 699 * @throws InterruptedException if <code>interrupt()</code> was called for 700 * the receiver while it was in the <code>join()</code> call 701 * @see Object#notifyAll 702 * @see java.lang.ThreadDeath 703 */ 704 public final void join() throws InterruptedException { 705 VMThread t = vmThread; 706 if (t == null) { 707 return; 708 } 709 710 synchronized (t) { 711 while (isAlive()) { 712 t.wait(); 713 } 714 } 715 } 716 717 /** 718 * Blocks the current Thread (<code>Thread.currentThread()</code>) until 719 * the receiver finishes its execution and dies or the specified timeout 720 * expires, whatever happens first. 721 * 722 * @param millis The maximum time to wait (in milliseconds). 723 * @throws InterruptedException if <code>interrupt()</code> was called for 724 * the receiver while it was in the <code>join()</code> call 725 * @see Object#notifyAll 726 * @see java.lang.ThreadDeath 727 */ 728 public final void join(long millis) throws InterruptedException { 729 join(millis, 0); 730 } 731 732 /** 733 * Blocks the current Thread (<code>Thread.currentThread()</code>) until 734 * the receiver finishes its execution and dies or the specified timeout 735 * expires, whatever happens first. 736 * 737 * @param millis The maximum time to wait (in milliseconds). 738 * @param nanos Extra nanosecond precision 739 * @throws InterruptedException if <code>interrupt()</code> was called for 740 * the receiver while it was in the <code>join()</code> call 741 * @see Object#notifyAll 742 * @see java.lang.ThreadDeath 743 */ 744 public final void join(long millis, int nanos) throws InterruptedException { 745 if (millis < 0 || nanos < 0 || nanos >= NANOS_PER_MILLI) { 746 throw new IllegalArgumentException(); 747 } 748 749 // avoid overflow: if total > 292,277 years, just wait forever 750 boolean overflow = millis >= (Long.MAX_VALUE - nanos) / NANOS_PER_MILLI; 751 boolean forever = (millis | nanos) == 0; 752 if (forever | overflow) { 753 join(); 754 return; 755 } 756 757 VMThread t = vmThread; 758 if (t == null) { 759 return; 760 } 761 762 synchronized (t) { 763 if (!isAlive()) { 764 return; 765 } 766 767 // guaranteed not to overflow 768 long nanosToWait = millis * NANOS_PER_MILLI + nanos; 769 770 // wait until this thread completes or the timeout has elapsed 771 long start = System.nanoTime(); 772 while (true) { 773 t.wait(millis, nanos); 774 if (!isAlive()) { 775 break; 776 } 777 long nanosElapsed = System.nanoTime() - start; 778 long nanosRemaining = nanosToWait - nanosElapsed; 779 if (nanosRemaining <= 0) { 780 break; 781 } 782 millis = nanosRemaining / NANOS_PER_MILLI; 783 nanos = (int) (nanosRemaining - millis * NANOS_PER_MILLI); 784 } 785 } 786 } 787 788 /** 789 * Throws {@code UnsupportedOperationException}. 790 * 791 * @see Thread#suspend() 792 * @deprecated Used with deprecated method {@link Thread#suspend} 793 */ 794 @Deprecated 795 public final void resume() { 796 throw new UnsupportedOperationException(); 797 } 798 799 /** 800 * Calls the <code>run()</code> method of the Runnable object the receiver 801 * holds. If no Runnable is set, does nothing. 802 * 803 * @see Thread#start 804 */ 805 public void run() { 806 if (target != null) { 807 target.run(); 808 } 809 } 810 811 /** 812 * Set the context ClassLoader for the receiver. 813 * 814 * @param cl The context ClassLoader 815 * @see #getContextClassLoader() 816 */ 817 public void setContextClassLoader(ClassLoader cl) { 818 contextClassLoader = cl; 819 } 820 821 /** 822 * Set if the receiver is a daemon Thread or not. This can only be done 823 * before the Thread starts running. 824 * 825 * @param isDaemon 826 * indicates whether the Thread should be daemon or not 827 * @see Thread#isDaemon 828 */ 829 public final void setDaemon(boolean isDaemon) { 830 if (hasBeenStarted) { 831 throw new IllegalThreadStateException("Thread already started."); // TODO Externalize? 832 } 833 834 if (vmThread == null) { 835 daemon = isDaemon; 836 } 837 } 838 839 /** 840 * Sets the default uncaught exception handler. This handler is invoked in 841 * case any Thread dies due to an unhandled exception. 842 * 843 * @param handler 844 * The handler to set or null. 845 */ 846 public static void setDefaultUncaughtExceptionHandler(UncaughtExceptionHandler handler) { 847 Thread.defaultUncaughtHandler = handler; 848 } 849 850 /** 851 * Adds a runnable to be invoked upon interruption. If this thread has 852 * already been interrupted, the runnable will be invoked immediately. The 853 * action should be idempotent as it may be invoked multiple times for a 854 * single interruption. 855 * 856 * <p>Each call to this method must be matched with a corresponding call to 857 * {@link #popInterruptAction$}. 858 * 859 * @hide used by NIO 860 */ 861 public final void pushInterruptAction$(Runnable interruptAction) { 862 synchronized (interruptActions) { 863 interruptActions.add(interruptAction); 864 } 865 866 if (interruptAction != null && isInterrupted()) { 867 interruptAction.run(); 868 } 869 } 870 871 /** 872 * Removes {@code interruptAction} so it is not invoked upon interruption. 873 * 874 * @param interruptAction the pushed action, used to check that the call 875 * stack is correctly nested. 876 * 877 * @hide used by NIO 878 */ 879 public final void popInterruptAction$(Runnable interruptAction) { 880 synchronized (interruptActions) { 881 Runnable removed = interruptActions.remove(interruptActions.size() - 1); 882 if (interruptAction != removed) { 883 throw new IllegalArgumentException( 884 "Expected " + interruptAction + " but was " + removed); 885 } 886 } 887 } 888 889 /** 890 * Sets the name of the Thread. 891 * 892 * @param threadName the new name for the Thread 893 * @see Thread#getName 894 */ 895 public final void setName(String threadName) { 896 if (threadName == null) { 897 throw new NullPointerException(); 898 } 899 900 name = threadName; 901 VMThread vmt = this.vmThread; 902 if (vmt != null) { 903 /* notify the VM that the thread name has changed */ 904 vmt.nameChanged(threadName); 905 } 906 } 907 908 /** 909 * Sets the priority of the Thread. Note that the final priority set may not 910 * be the parameter that was passed - it will depend on the receiver's 911 * ThreadGroup. The priority cannot be set to be higher than the receiver's 912 * ThreadGroup's maxPriority(). 913 * 914 * @param priority 915 * new priority for the Thread 916 * @throws IllegalArgumentException 917 * if the new priority is greater than Thread.MAX_PRIORITY or 918 * less than Thread.MIN_PRIORITY 919 * @see Thread#getPriority 920 */ 921 public final void setPriority(int priority) { 922 if (priority < Thread.MIN_PRIORITY || priority > Thread.MAX_PRIORITY) { 923 throw new IllegalArgumentException("Priority out of range"); // TODO Externalize? 924 } 925 926 if (priority > group.getMaxPriority()) { 927 priority = group.getMaxPriority(); 928 } 929 930 this.priority = priority; 931 932 VMThread vmt = this.vmThread; 933 if (vmt != null) { 934 vmt.setPriority(priority); 935 } 936 } 937 938 /** 939 * <p> 940 * Sets the uncaught exception handler. This handler is invoked in case this 941 * Thread dies due to an unhandled exception. 942 * </p> 943 * 944 * @param handler 945 * The handler to set or <code>null</code>. 946 */ 947 public void setUncaughtExceptionHandler(UncaughtExceptionHandler handler) { 948 uncaughtHandler = handler; 949 } 950 951 /** 952 * Causes the thread which sent this message to sleep for the given interval 953 * of time (given in milliseconds). The precision is not guaranteed - the 954 * Thread may sleep more or less than requested. 955 * 956 * @param time 957 * The time to sleep in milliseconds. 958 * @throws InterruptedException 959 * if <code>interrupt()</code> was called for this Thread while 960 * it was sleeping 961 * @see Thread#interrupt() 962 */ 963 public static void sleep(long time) throws InterruptedException { 964 Thread.sleep(time, 0); 965 } 966 967 /** 968 * Causes the thread which sent this message to sleep for the given interval 969 * of time (given in milliseconds and nanoseconds). The precision is not 970 * guaranteed - the Thread may sleep more or less than requested. 971 * 972 * @param millis 973 * The time to sleep in milliseconds. 974 * @param nanos 975 * Extra nanosecond precision 976 * @throws InterruptedException 977 * if <code>interrupt()</code> was called for this Thread while 978 * it was sleeping 979 * @see Thread#interrupt() 980 */ 981 public static void sleep(long millis, int nanos) throws InterruptedException { 982 VMThread.sleep(millis, nanos); 983 } 984 985 /** 986 * Starts the new Thread of execution. The <code>run()</code> method of 987 * the receiver will be called by the receiver Thread itself (and not the 988 * Thread calling <code>start()</code>). 989 * 990 * @throws IllegalThreadStateException if the Thread has been started before 991 * 992 * @see Thread#run 993 */ 994 public synchronized void start() { 995 if (hasBeenStarted) { 996 throw new IllegalThreadStateException("Thread already started."); // TODO Externalize? 997 } 998 999 hasBeenStarted = true; 1000 1001 VMThread.create(this, stackSize); 1002 } 1003 1004 /** 1005 * Requests the receiver Thread to stop and throw ThreadDeath. The Thread is 1006 * resumed if it was suspended and awakened if it was sleeping, so that it 1007 * can proceed to throw ThreadDeath. 1008 * 1009 * @deprecated because stopping a thread in this manner is unsafe and can 1010 * leave your application and the VM in an unpredictable state. 1011 */ 1012 @Deprecated 1013 public final void stop() { 1014 stop(new ThreadDeath()); 1015 } 1016 1017 /** 1018 * Throws {@code UnsupportedOperationException}. 1019 * 1020 * @throws NullPointerException if <code>throwable()</code> is 1021 * <code>null</code> 1022 * @deprecated because stopping a thread in this manner is unsafe and can 1023 * leave your application and the VM in an unpredictable state. 1024 */ 1025 @Deprecated 1026 public final synchronized void stop(Throwable throwable) { 1027 throw new UnsupportedOperationException(); 1028 } 1029 1030 /** 1031 * Throws {@code UnsupportedOperationException}. 1032 * 1033 * @see Thread#resume() 1034 * @deprecated May cause deadlocks. 1035 */ 1036 @Deprecated 1037 public final void suspend() { 1038 throw new UnsupportedOperationException(); 1039 } 1040 1041 /** 1042 * Returns a string containing a concise, human-readable description of the 1043 * Thread. It includes the Thread's name, priority, and group name. 1044 * 1045 * @return a printable representation for the receiver. 1046 */ 1047 @Override 1048 public String toString() { 1049 return "Thread[" + name + "," + priority + "," + group.getName() + "]"; 1050 } 1051 1052 /** 1053 * Causes the calling Thread to yield execution time to another Thread that 1054 * is ready to run. The actual scheduling is implementation-dependent. 1055 */ 1056 public static void yield() { 1057 VMThread.yield(); 1058 } 1059 1060 /** 1061 * Indicates whether the current Thread has a monitor lock on the specified 1062 * object. 1063 * 1064 * @param object the object to test for the monitor lock 1065 * @return true if the current thread has a monitor lock on the specified 1066 * object; false otherwise 1067 */ 1068 public static boolean holdsLock(Object object) { 1069 return currentThread().vmThread.holdsLock(object); 1070 } 1071 1072 /** 1073 * Implemented by objects that want to handle cases where a thread is being 1074 * terminated by an uncaught exception. Upon such termination, the handler 1075 * is notified of the terminating thread and causal exception. If there is 1076 * no explicit handler set then the thread's group is the default handler. 1077 */ 1078 public static interface UncaughtExceptionHandler { 1079 /** 1080 * The thread is being terminated by an uncaught exception. Further 1081 * exceptions thrown in this method are prevent the remainder of the 1082 * method from executing, but are otherwise ignored. 1083 * 1084 * @param thread the thread that has an uncaught exception 1085 * @param ex the exception that was thrown 1086 */ 1087 void uncaughtException(Thread thread, Throwable ex); 1088 } 1089 1090 /** 1091 * Unparks this thread. This unblocks the thread it if it was 1092 * previously parked, or indicates that the thread is "preemptively 1093 * unparked" if it wasn't already parked. The latter means that the 1094 * next time the thread is told to park, it will merely clear its 1095 * latent park bit and carry on without blocking. 1096 * 1097 * <p>See {@link java.util.concurrent.locks.LockSupport} for more 1098 * in-depth information of the behavior of this method.</p> 1099 * 1100 * @hide for Unsafe 1101 */ 1102 public void unpark() { 1103 VMThread vmt = vmThread; 1104 1105 if (vmt == null) { 1106 /* 1107 * vmThread is null before the thread is start()ed. In 1108 * this case, we just go ahead and set the state to 1109 * PREEMPTIVELY_UNPARKED. Since this happens before the 1110 * thread is started, we don't have to worry about 1111 * synchronizing with it. 1112 */ 1113 parkState = ParkState.PREEMPTIVELY_UNPARKED; 1114 return; 1115 } 1116 1117 synchronized (vmt) { 1118 switch (parkState) { 1119 case ParkState.PREEMPTIVELY_UNPARKED: { 1120 /* 1121 * Nothing to do in this case: By definition, a 1122 * preemptively unparked thread is to remain in 1123 * the preemptively unparked state if it is told 1124 * to unpark. 1125 */ 1126 break; 1127 } 1128 case ParkState.UNPARKED: { 1129 parkState = ParkState.PREEMPTIVELY_UNPARKED; 1130 break; 1131 } 1132 default /*parked*/: { 1133 parkState = ParkState.UNPARKED; 1134 vmt.notifyAll(); 1135 break; 1136 } 1137 } 1138 } 1139 } 1140 1141 /** 1142 * Parks the current thread for a particular number of nanoseconds, or 1143 * indefinitely. If not indefinitely, this method unparks the thread 1144 * after the given number of nanoseconds if no other thread unparks it 1145 * first. If the thread has been "preemptively unparked," this method 1146 * cancels that unparking and returns immediately. This method may 1147 * also return spuriously (that is, without the thread being told to 1148 * unpark and without the indicated amount of time elapsing). 1149 * 1150 * <p>See {@link java.util.concurrent.locks.LockSupport} for more 1151 * in-depth information of the behavior of this method.</p> 1152 * 1153 * <p>This method must only be called when <code>this</code> is the current 1154 * thread. 1155 * 1156 * @param nanos number of nanoseconds to park for or <code>0</code> 1157 * to park indefinitely 1158 * @throws IllegalArgumentException thrown if <code>nanos < 0</code> 1159 * 1160 * @hide for Unsafe 1161 */ 1162 public void parkFor(long nanos) { 1163 VMThread vmt = vmThread; 1164 1165 if (vmt == null) { 1166 // Running threads should always have an associated vmThread. 1167 throw new AssertionError(); 1168 } 1169 1170 synchronized (vmt) { 1171 switch (parkState) { 1172 case ParkState.PREEMPTIVELY_UNPARKED: { 1173 parkState = ParkState.UNPARKED; 1174 break; 1175 } 1176 case ParkState.UNPARKED: { 1177 long millis = nanos / NANOS_PER_MILLI; 1178 nanos %= NANOS_PER_MILLI; 1179 1180 parkState = ParkState.PARKED; 1181 try { 1182 vmt.wait(millis, (int) nanos); 1183 } catch (InterruptedException ex) { 1184 interrupt(); 1185 } finally { 1186 /* 1187 * Note: If parkState manages to become 1188 * PREEMPTIVELY_UNPARKED before hitting this 1189 * code, it should left in that state. 1190 */ 1191 if (parkState == ParkState.PARKED) { 1192 parkState = ParkState.UNPARKED; 1193 } 1194 } 1195 break; 1196 } 1197 default /*parked*/: { 1198 throw new AssertionError( 1199 "shouldn't happen: attempt to repark"); 1200 } 1201 } 1202 } 1203 } 1204 1205 /** 1206 * Parks the current thread until the specified system time. This 1207 * method attempts to unpark the current thread immediately after 1208 * <code>System.currentTimeMillis()</code> reaches the specified 1209 * value, if no other thread unparks it first. If the thread has 1210 * been "preemptively unparked," this method cancels that 1211 * unparking and returns immediately. This method may also return 1212 * spuriously (that is, without the thread being told to unpark 1213 * and without the indicated amount of time elapsing). 1214 * 1215 * <p>See {@link java.util.concurrent.locks.LockSupport} for more 1216 * in-depth information of the behavior of this method.</p> 1217 * 1218 * <p>This method must only be called when <code>this</code> is the 1219 * current thread. 1220 * 1221 * @param time the time after which the thread should be unparked, 1222 * in absolute milliseconds-since-the-epoch 1223 * 1224 * @hide for Unsafe 1225 */ 1226 public void parkUntil(long time) { 1227 VMThread vmt = vmThread; 1228 1229 if (vmt == null) { 1230 // Running threads should always have an associated vmThread. 1231 throw new AssertionError(); 1232 } 1233 1234 synchronized (vmt) { 1235 /* 1236 * Note: This conflates the two time bases of "wall clock" 1237 * time and "monotonic uptime" time. However, given that 1238 * the underlying system can only wait on monotonic time, 1239 * it is unclear if there is any way to avoid the 1240 * conflation. The downside here is that if, having 1241 * calculated the delay, the wall clock gets moved ahead, 1242 * this method may not return until well after the wall 1243 * clock has reached the originally designated time. The 1244 * reverse problem (the wall clock being turned back) 1245 * isn't a big deal, since this method is allowed to 1246 * spuriously return for any reason, and this situation 1247 * can safely be construed as just such a spurious return. 1248 */ 1249 long delayMillis = time - System.currentTimeMillis(); 1250 1251 if (delayMillis <= 0) { 1252 parkState = ParkState.UNPARKED; 1253 } else { 1254 parkFor(delayMillis * NANOS_PER_MILLI); 1255 } 1256 } 1257 } 1258 }
Thread Localexpress
1 /* 2 * Copyright (C) 2008 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package java.lang; 18 19 import java.lang.ref.Reference; 20 import java.lang.ref.WeakReference; 21 import java.util.concurrent.atomic.AtomicInteger; 22 23 /** 24 * Implements a thread-local storage, that is, a variable for which each thread 25 * has its own value. All threads share the same {@code ThreadLocal} object, 26 * but each sees a different value when accessing it, and changes made by one 27 * thread do not affect the other threads. The implementation supports 28 * {@code null} values. 29 * 30 * @see java.lang.Thread 31 * @author Bob Lee 32 */ 33 public class ThreadLocal<T> { 34 35 /* Thanks to Josh Bloch and Doug Lea for code reviews and impl advice. */ 36 37 /** 38 * Creates a new thread-local variable. 39 */ 40 public ThreadLocal() {} 41 42 /** 43 * Returns the value of this variable for the current thread. If an entry 44 * doesn't yet exist for this variable on this thread, this method will 45 * create an entry, populating the value with the result of 46 * {@link #initialValue()}. 47 * 48 * @return the current value of the variable for the calling thread. 49 */ 50 @SuppressWarnings("unchecked") 51 public T get() { 52 // Optimized for the fast path. 53 Thread currentThread = Thread.currentThread(); 54 Values values = values(currentThread); 55 if (values != null) { 56 Object[] table = values.table; 57 int index = hash & values.mask; 58 if (this.reference == table[index]) { 59 return (T) table[index + 1]; 60 } 61 } else { 62 values = initializeValues(currentThread); 63 } 64 65 return (T) values.getAfterMiss(this); 66 } 67 68 /** 69 * Provides the initial value of this variable for the current thread. 70 * The default implementation returns {@code null}. 71 * 72 * @return the initial value of the variable. 73 */ 74 protected T initialValue() { 75 return null; 76 } 77 78 /** 79 * Sets the value of this variable for the current thread. If set to 80 * {@code null}, the value will be set to null and the underlying entry will 81 * still be present. 82 * 83 * @param value the new value of the variable for the caller thread. 84 */ 85 public void set(T value) { 86 Thread currentThread = Thread.currentThread(); 87 Values values = values(currentThread); 88 if (values == null) { 89 values = initializeValues(currentThread); 90 } 91 values.put(this, value); 92 } 93 94 /** 95 * Removes the entry for this variable in the current thread. If this call 96 * is followed by a {@link #get()} before a {@link #set}, 97 * {@code #get()} will call {@link #initialValue()} and create a new 98 * entry with the resulting value. 99 * 100 * @since 1.5 101 */ 102 public void remove() { 103 Thread currentThread = Thread.currentThread(); 104 Values values = values(currentThread); 105 if (values != null) { 106 values.remove(this); 107 } 108 } 109 110 /** 111 * Creates Values instance for this thread and variable type. 112 */ 113 Values initializeValues(Thread current) { 114 return current.localValues = new Values(); 115 } 116 117 /** 118 * Gets Values instance for this thread and variable type. 119 */ 120 Values values(Thread current) { 121 return current.localValues; 122 } 123 124 /** Weak reference to this thread local instance. */ 125 private final Reference<ThreadLocal<T>> reference 126 = new WeakReference<ThreadLocal<T>>(this); 127 128 /** Hash counter. */ 129 private static AtomicInteger hashCounter = new AtomicInteger(0); 130 131 /** 132 * Internal hash. We deliberately don't bother with #hashCode(). 133 * Hashes must be even. This ensures that the result of 134 * (hash & (table.length - 1)) points to a key and not a value. 135 * 136 * We increment by Doug Lea's Magic Number(TM) (*2 since keys are in 137 * every other bucket) to help prevent clustering. 138 */ 139 private final int hash = hashCounter.getAndAdd(0x61c88647 * 2); 140 141 /** 142 * Per-thread map of ThreadLocal instances to values. 143 */ 144 static class Values { 145 146 /** 147 * Size must always be a power of 2. 148 */ 149 private static final int INITIAL_SIZE = 16; 150 151 /** 152 * Placeholder for deleted entries. 153 */ 154 private static final Object TOMBSTONE = new Object(); 155 156 /** 157 * Map entries. Contains alternating keys (ThreadLocal) and values. 158 * The length is always a power of 2. 159 */ 160 private Object[] table; 161 162 /** Used to turn hashes into indices. */ 163 private int mask; 164 165 /** Number of live entries. */ 166 private int size; 167 168 /** Number of tombstones. */ 169 private int tombstones; 170 171 /** Maximum number of live entries and tombstones. */ 172 private int maximumLoad; 173 174 /** Points to the next cell to clean up. */ 175 private int clean; 176 177 /** 178 * Constructs a new, empty instance. 179 */ 180 Values() { 181 initializeTable(INITIAL_SIZE); 182 this.size = 0; 183 this.tombstones = 0; 184 } 185 186 /** 187 * Used for InheritableThreadLocals. 188 */ 189 Values(Values fromParent) { 190 this.table = fromParent.table.clone(); 191 this.mask = fromParent.mask; 192 this.size = fromParent.size; 193 this.tombstones = fromParent.tombstones; 194 this.maximumLoad = fromParent.maximumLoad; 195 this.clean = fromParent.clean; 196 inheritValues(fromParent); 197 } 198 199 /** 200 * Inherits values from a parent thread. 201 */ 202 @SuppressWarnings({"unchecked"}) 203 private void inheritValues(Values fromParent) { 204 // Transfer values from parent to child thread. 205 Object[] table = this.table; 206 for (int i = table.length - 2; i >= 0; i -= 2) { 207 Object k = table[i]; 208 209 if (k == null || k == TOMBSTONE) { 210 // Skip this entry. 211 continue; 212 } 213 214 // The table can only contain null, tombstones and references. 215 Reference<InheritableThreadLocal<?>> reference 216 = (Reference<InheritableThreadLocal<?>>) k; 217 // Raw type enables us to pass in an Object below. 218 InheritableThreadLocal key = reference.get(); 219 if (key != null) { 220 // Replace value with filtered value. 221 // We should just let exceptions bubble out and tank 222 // the thread creation 223 table[i + 1] = key.childValue(fromParent.table[i + 1]); 224 } else { 225 // The key was reclaimed. 226 table[i] = TOMBSTONE; 227 table[i + 1] = null; 228 fromParent.table[i] = TOMBSTONE; 229 fromParent.table[i + 1] = null; 230 231 tombstones++; 232 fromParent.tombstones++; 233 234 size--; 235 fromParent.size--; 236 } 237 } 238 } 239 240 /** 241 * Creates a new, empty table with the given capacity. 242 */ 243 private void initializeTable(int capacity) { 244 this.table = new Object[capacity * 2]; 245 this.mask = table.length - 1; 246 this.clean = 0; 247 this.maximumLoad = capacity * 2 / 3; // 2/3 248 } 249 250 /** 251 * Cleans up after garbage-collected thread locals. 252 */ 253 private void cleanUp() { 254 if (rehash()) { 255 // If we rehashed, we needn't clean up (clean up happens as 256 // a side effect). 257 return; 258 } 259 260 if (size == 0) { 261 // No live entries == nothing to clean. 262 return; 263 } 264 265 // Clean log(table.length) entries picking up where we left off 266 // last time. 267 int index = clean; 268 Object[] table = this.table; 269 for (int counter = table.length; counter > 0; counter >>= 1, 270 index = next(index)) { 271 Object k = table[index]; 272 273 if (k == TOMBSTONE || k == null) { 274 continue; // on to next entry 275 } 276 277 // The table can only contain null, tombstones and references. 278 @SuppressWarnings("unchecked") 279 Reference<ThreadLocal<?>> reference 280 = (Reference<ThreadLocal<?>>) k; 281 if (reference.get() == null) { 282 // This thread local was reclaimed by the garbage collector. 283 table[index] = TOMBSTONE; 284 table[index + 1] = null; 285 tombstones++; 286 size--; 287 } 288 } 289 290 // Point cursor to next index. 291 clean = index; 292 } 293 294 /** 295 * Rehashes the table, expanding or contracting it as necessary. 296 * Gets rid of tombstones. Returns true if a rehash occurred. 297 * We must rehash every time we fill a null slot; we depend on the 298 * presence of null slots to end searches (otherwise, we'll infinitely 299 * loop). 300 */ 301 private boolean rehash() { 302 if (tombstones + size < maximumLoad) { 303 return false; 304 } 305 306 int capacity = table.length >> 1; 307 308 // Default to the same capacity. This will create a table of the 309 // same size and move over the live entries, analogous to a 310 // garbage collection. This should only happen if you churn a 311 // bunch of thread local garbage (removing and reinserting 312 // the same thread locals over and over will overwrite tombstones 313 // and not fill up the table). 314 int newCapacity = capacity; 315 316 if (size > (capacity >> 1)) { 317 // More than 1/2 filled w/ live entries. 318 // Double size. 319 newCapacity = capacity * 2; 320 } 321 322 Object[] oldTable = this.table; 323 324 // Allocate new table. 325 initializeTable(newCapacity); 326 327 // We won't have any tombstones after this. 328 this.tombstones = 0; 329 330 // If we have no live entries, we can quit here. 331 if (size == 0) { 332 return true; 333 } 334 335 // Move over entries. 336 for (int i = oldTable.length - 2; i >= 0; i -= 2) { 337 Object k = oldTable[i]; 338 if (k == null || k == TOMBSTONE) { 339 // Skip this entry. 340 continue; 341 } 342 343 // The table can only contain null, tombstones and references. 344 @SuppressWarnings("unchecked") 345 Reference<ThreadLocal<?>> reference 346 = (Reference<ThreadLocal<?>>) k; 347 ThreadLocal<?> key = reference.get(); 348 if (key != null) { 349 // Entry is still live. Move it over. 350 add(key, oldTable[i + 1]); 351 } else { 352 // The key was reclaimed. 353 size--; 354 } 355 } 356 357 return true; 358 } 359 360 /** 361 * Adds an entry during rehashing. Compared to put(), this method 362 * doesn't have to clean up, check for existing entries, account for 363 * tombstones, etc. 364 */ 365 void add(ThreadLocal<?> key, Object value) { 366 for (int index = key.hash & mask;; index = next(index)) { 367 Object k = table[index]; 368 if (k == null) { 369 table[index] = key.reference; 370 table[index + 1] = value; 371 return; 372 } 373 } 374 } 375 376 /** 377 * Sets entry for given ThreadLocal to given value, creating an 378 * entry if necessary. 379 */ 380 void put(ThreadLocal<?> key, Object value) { 381 cleanUp(); 382 383 // Keep track of first tombstone. That's where we want to go back 384 // and add an entry if necessary. 385 int firstTombstone = -1; 386 387 for (int index = key.hash & mask;; index = next(index)) { 388 Object k = table[index]; 389 390 if (k == key.reference) { 391 // Replace existing entry. 392 table[index + 1] = value; 393 return; 394 } 395 396 if (k == null) { 397 if (firstTombstone == -1) { 398 // Fill in null slot. 399 table[index] = key.reference; 400 table[index + 1] = value; 401 size++; 402 return; 403 } 404 405 // Go back and replace first tombstone. 406 table[firstTombstone] = key.reference; 407 table[firstTombstone + 1] = value; 408 tombstones--; 409 size++; 410 return; 411 } 412 413 // Remember first tombstone. 414 if (firstTombstone == -1 && k == TOMBSTONE) { 415 firstTombstone = index; 416 } 417 } 418 } 419 420 /** 421 * Gets value for given ThreadLocal after not finding it in the first 422 * slot. 423 */ 424 Object getAfterMiss(ThreadLocal<?> key) { 425 Object[] table = this.table; 426 int index = key.hash & mask; 427 428 // If the first slot is empty, the search is over. 429 if (table[index] == null) { 430 Object value = key.initialValue(); 431 432 // If the table is still the same and the slot is still empty... 433 if (this.table == table && table[index] == null) { 434 table[index] = key.reference; 435 table[index + 1] = value; 436 size++; 437 438 cleanUp(); 439 return value; 440 } 441 442 // The table changed during initialValue(). 443 put(key, value); 444 return value; 445 } 446 447 // Keep track of first tombstone. That's where we want to go back 448 // and add an entry if necessary. 449 int firstTombstone = -1; 450 451 // Continue search. 452 for (index = next(index);; index = next(index)) { 453 Object reference = table[index]; 454 if (reference == key.reference) { 455 return table[index + 1]; 456 } 457 458 // If no entry was found... 459 if (reference == null) { 460 Object value = key.initialValue(); 461 462 // If the table is still the same... 463 if (this.table == table) { 464 // If we passed a tombstone and that slot still 465 // contains a tombstone... 466 if (firstTombstone > -1 467 && table[firstTombstone] == TOMBSTONE) { 468 table[firstTombstone] = key.reference; 469 table[firstTombstone + 1] = value; 470 tombstones--; 471 size++; 472 473 // No need to clean up here. We aren't filling 474 // in a null slot. 475 return value; 476 } 477 478 // If this slot is still empty... 479 if (table[index] == null) { 480 table[index] = key.reference; 481 table[index + 1] = value; 482 size++; 483 484 cleanUp(); 485 return value; 486 } 487 } 488 489 // The table changed during initialValue(). 490 put(key, value); 491 return value; 492 } 493 494 if (firstTombstone == -1 && reference == TOMBSTONE) { 495 // Keep track of this tombstone so we can overwrite it. 496 firstTombstone = index; 497 } 498 } 499 } 500 501 /** 502 * Removes entry for the given ThreadLocal. 503 */ 504 void remove(ThreadLocal<?> key) { 505 cleanUp(); 506 507 for (int index = key.hash & mask;; index = next(index)) { 508 Object reference = table[index]; 509 510 if (reference == key.reference) { 511 // Success! 512 table[index] = TOMBSTONE; 513 table[index + 1] = null; 514 tombstones++; 515 size--; 516 return; 517 } 518 519 if (reference == null) { 520 // No entry found. 521 return; 522 } 523 } 524 } 525 526 /** 527 * Gets the next index. If we're at the end of the table, we wrap back 528 * around to 0. 529 */ 530 private int next(int index) { 531 return (index + 2) & mask; 532 } 533 } 534 }
Thead Groupapache
1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18 package java.lang; 19 20 import java.lang.ref.WeakReference; 21 import java.util.ArrayList; 22 import java.util.Iterator; 23 import java.util.List; 24 import libcore.util.CollectionUtils; 25 26 /** 27 * {@code ThreadGroup} is a means of organizing threads into a hierarchical structure. 28 * This class is obsolete. See <i>Effective Java</i> Item 73, "Avoid thread groups" for details. 29 * @see Thread 30 */ 31 public class ThreadGroup implements Thread.UncaughtExceptionHandler { 32 33 // Name of this ThreadGroup 34 // VM needs this field name for debugging. 35 private String name; 36 37 // Maximum priority for Threads inside this ThreadGroup 38 private int maxPriority = Thread.MAX_PRIORITY; 39 40 // The ThreadGroup to which this ThreadGroup belongs 41 // VM needs this field name for debugging. 42 final ThreadGroup parent; 43 44 /** 45 * Weak references to the threads in this group. 46 * Access is guarded by synchronizing on this field. 47 */ 48 private final List<WeakReference<Thread>> threadRefs = new ArrayList<WeakReference<Thread>>(5); 49 50 /** 51 * View of the threads. 52 * Access is guarded by synchronizing on threadRefs. 53 */ 54 private final Iterable<Thread> threads = CollectionUtils.dereferenceIterable(threadRefs, true); 55 56 /** 57 * Thread groups. Access is guarded by synchronizing on this field. 58 */ 59 private final List<ThreadGroup> groups = new ArrayList<ThreadGroup>(3); 60 61 // Whether this ThreadGroup is a daemon ThreadGroup or not 62 private boolean isDaemon; 63 64 // Whether this ThreadGroup has already been destroyed or not 65 private boolean isDestroyed; 66 67 /* the VM uses these directly; do not rename */ 68 static final ThreadGroup mSystem = new ThreadGroup(); 69 static final ThreadGroup mMain = new ThreadGroup(mSystem, "main"); 70 71 /** 72 * Constructs a new {@code ThreadGroup} with the given name. The new {@code ThreadGroup} 73 * will be child of the {@code ThreadGroup} to which the calling thread belongs. 74 * 75 * @param name the name 76 * @see Thread#currentThread 77 */ 78 public ThreadGroup(String name) { 79 this(Thread.currentThread().getThreadGroup(), name); 80 } 81 82 /** 83 * Constructs a new {@code ThreadGroup} with the given name, as a child of the 84 * given {@code ThreadGroup}. 85 * 86 * @param parent the parent 87 * @param name the name 88 * @throws NullPointerException if {@code parent == null} 89 * @throws IllegalThreadStateException if {@code parent} has been 90 * destroyed already 91 */ 92 public ThreadGroup(ThreadGroup parent, String name) { 93 if (parent == null) { 94 throw new NullPointerException("parent == null"); 95 } 96 this.name = name; 97 this.parent = parent; 98 if (parent != null) { 99 parent.add(this); 100 this.setMaxPriority(parent.getMaxPriority()); 101 if (parent.isDaemon()) { 102 this.setDaemon(true); 103 } 104 } 105 } 106 107 /** 108 * Initialize the special "system" ThreadGroup. Was "main" in Harmony, 109 * but we have an additional group above that in Android. 110 */ 111 private ThreadGroup() { 112 this.name = "system"; 113 this.parent = null; 114 } 115 116 /** 117 * Returns the number of running {@code Thread}s which are children of this thread group, 118 * directly or indirectly. 119 * 120 * @return the number of children 121 */ 122 public int activeCount() { 123 int count = 0; 124 synchronized (threadRefs) { 125 for (Thread thread : threads) { 126 if (thread.isAlive()) { 127 count++; 128 } 129 } 130 } 131 synchronized (groups) { 132 for (ThreadGroup group : groups) { 133 count += group.activeCount(); 134 } 135 } 136 return count; 137 } 138 139 /** 140 * Returns the number of {@code ThreadGroup}s which are children of this group, 141 * directly or indirectly. 142 * 143 * @return the number of children 144 */ 145 public int activeGroupCount() { 146 int count = 0; 147 synchronized (groups) { 148 for (ThreadGroup group : groups) { 149 // One for this group & the subgroups 150 count += 1 + group.activeGroupCount(); 151 } 152 } 153 return count; 154 } 155 156 /** 157 * Adds a {@code ThreadGroup} to this thread group. 158 * 159 * @param g ThreadGroup to add 160 * @throws IllegalThreadStateException if this group has been destroyed already 161 */ 162 private void add(ThreadGroup g) throws IllegalThreadStateException { 163 synchronized (groups) { 164 if (isDestroyed) { 165 throw new IllegalThreadStateException(); 166 } 167 groups.add(g); 168 } 169 } 170 171 /** 172 * Does nothing. The definition of this method depends on the deprecated 173 * method {@link #suspend()}. The exact behavior of this call was never 174 * specified. 175 * 176 * @param b Used to control low memory implicit suspension 177 * @return {@code true} (always) 178 * 179 * @deprecated Required deprecated method suspend(). 180 */ 181 @Deprecated 182 public boolean allowThreadSuspension(boolean b) { 183 // Does not apply to this VM, no-op 184 return true; 185 } 186 187 /** 188 * Does nothing. 189 */ 190 public final void checkAccess() { 191 } 192 193 /** 194 * Destroys this thread group and recursively all its subgroups. It is only legal 195 * to destroy a {@code ThreadGroup} that has no threads in it. Any daemon 196 * {@code ThreadGroup} is destroyed automatically when it becomes empty (no threads 197 * or thread groups in it). 198 * 199 * @throws IllegalThreadStateException if this thread group or any of its 200 * subgroups has been destroyed already or if it still contains 201 * threads. 202 */ 203 public final void destroy() { 204 synchronized (threadRefs) { 205 synchronized (groups) { 206 if (isDestroyed) { 207 throw new IllegalThreadStateException( 208 "Thread group was already destroyed: " 209 + (this.name != null ? this.name : "n/a")); 210 } 211 if (threads.iterator().hasNext()) { 212 throw new IllegalThreadStateException( 213 "Thread group still contains threads: " 214 + (this.name != null ? this.name : "n/a")); 215 } 216 // Call recursively for subgroups 217 while (!groups.isEmpty()) { 218 // We always get the first element - remember, when the 219 // child dies it removes itself from our collection. See 220 // below. 221 groups.get(0).destroy(); 222 } 223 224 if (parent != null) { 225 parent.remove(this); 226 } 227 228 // Now that the ThreadGroup is really destroyed it can be tagged as so 229 this.isDestroyed = true; 230 } 231 } 232 } 233 234 /* 235 * Auxiliary method that destroys this thread group and recursively all its 236 * subgroups if this is a daemon ThreadGroup. 237 * 238 * @see #destroy 239 * @see #setDaemon 240 * @see #isDaemon 241 */ 242 private void destroyIfEmptyDaemon() { 243 // Has to be non-destroyed daemon to make sense 244 synchronized (threadRefs) { 245 if (isDaemon && !isDestroyed && !threads.iterator().hasNext()) { 246 synchronized (groups) { 247 if (groups.isEmpty()) { 248 destroy(); 249 } 250 } 251 } 252 } 253 } 254 255 /** 256 * Iterates over all active threads in this group (and its sub-groups) and 257 * stores the threads in the given array. Returns when the array is full or 258 * no more threads remain, whichever happens first. 259 * 260 * <p>Note that this method will silently ignore any threads that don't fit in the 261 * supplied array. 262 * 263 * @param threads the array into which the {@code Thread}s will be copied 264 * @return the number of {@code Thread}s that were copied 265 */ 266 public int enumerate(Thread[] threads) { 267 return enumerate(threads, true); 268 } 269 270 /** 271 * Iterates over all active threads in this group (and, optionally, its 272 * sub-groups) and stores the threads in the given array. Returns when the 273 * array is full or no more threads remain, whichever happens first. 274 * 275 * <p>Note that this method will silently ignore any threads that don't fit in the 276 * supplied array. 277 * 278 * @param threads the array into which the {@code Thread}s will be copied 279 * @param recurse indicates whether {@code Thread}s in subgroups should be 280 * recursively copied as well 281 * @return the number of {@code Thread}s that were copied 282 */ 283 public int enumerate(Thread[] threads, boolean recurse) { 284 return enumerateGeneric(threads, recurse, 0, true); 285 } 286 287 /** 288 * Iterates over all thread groups in this group (and its sub-groups) and 289 * and stores the groups in the given array. Returns when the array is full 290 * or no more groups remain, whichever happens first. 291 * 292 * <p>Note that this method will silently ignore any thread groups that don't fit in the 293 * supplied array. 294 * 295 * @param groups the array into which the {@code ThreadGroup}s will be copied 296 * @return the number of {@code ThreadGroup}s that were copied 297 */ 298 public int enumerate(ThreadGroup[] groups) { 299 return enumerate(groups, true); 300 } 301 302 /** 303 * Iterates over all thread groups in this group (and, optionally, its 304 * sub-groups) and stores the groups in the given array. Returns when 305 * the array is full or no more groups remain, whichever happens first. 306 * 307 * <p>Note that this method will silently ignore any thread groups that don't fit in the 308 * supplied array. 309 * 310 * @param groups the array into which the {@code ThreadGroup}s will be copied 311 * @param recurse indicates whether {@code ThreadGroup}s in subgroups should be 312 * recursively copied as well or not 313 * @return the number of {@code ThreadGroup}s that were copied 314 */ 315 public int enumerate(ThreadGroup[] groups, boolean recurse) { 316 return enumerateGeneric(groups, recurse, 0, false); 317 } 318 319 /** 320 * Copies into <param>enumeration</param> starting at 321 * <param>enumerationIndex</param> all Threads or ThreadGroups in the 322 * receiver. If <param>recurse</param> is true, recursively enumerate the 323 * elements in subgroups. 324 * 325 * If the array passed as parameter is too small no exception is thrown - 326 * the extra elements are simply not copied. 327 * 328 * @param enumeration array into which the elements will be copied 329 * @param recurse Indicates whether subgroups should be enumerated or not 330 * @param enumerationIndex Indicates in which position of the enumeration 331 * array we are 332 * @param enumeratingThreads Indicates whether we are enumerating Threads or 333 * ThreadGroups 334 * @return How many elements were enumerated/copied over 335 */ 336 private int enumerateGeneric(Object[] enumeration, boolean recurse, int enumerationIndex, 337 boolean enumeratingThreads) { 338 if (enumeratingThreads) { 339 synchronized (threadRefs) { 340 // walk the references directly so we can iterate in reverse order 341 for (int i = threadRefs.size() - 1; i >= 0; --i) { 342 Thread thread = threadRefs.get(i).get(); 343 if (thread != null && thread.isAlive()) { 344 if (enumerationIndex >= enumeration.length) { 345 return enumerationIndex; 346 } 347 enumeration[enumerationIndex++] = thread; 348 } 349 } 350 } 351 } else { 352 synchronized (groups) { 353 for (int i = groups.size() - 1; i >= 0; --i) { 354 if (enumerationIndex >= enumeration.length) { 355 return enumerationIndex; 356 } 357 enumeration[enumerationIndex++] = groups.get(i); 358 } 359 } 360 } 361 362 if (recurse) { 363 synchronized (groups) { 364 for (ThreadGroup group : groups) { 365 if (enumerationIndex >= enumeration.length) { 366 return enumerationIndex; 367 } 368 enumerationIndex = group.enumerateGeneric(enumeration, recurse, 369 enumerationIndex, enumeratingThreads); 370 } 371 } 372 } 373 return enumerationIndex; 374 } 375 376 /** 377 * Returns the maximum allowed priority for a {@code Thread} in this thread group. 378 * 379 * @return the maximum priority 380 * 381 * @see #setMaxPriority 382 */ 383 public final int getMaxPriority() { 384 return maxPriority; 385 } 386 387 /** 388 * Returns the name of this thread group. 389 * 390 * @return the group's name 391 */ 392 public final String getName() { 393 return name; 394 } 395 396 /** 397 * Returns this thread group's parent {@code ThreadGroup}. It can be null if this 398 * is the the root ThreadGroup. 399 * 400 * @return the parent 401 */ 402 public final ThreadGroup getParent() { 403 return parent; 404 } 405 406 /** 407 * Interrupts every {@code Thread} in this group and recursively in all its 408 * subgroups. 409 * 410 * @see Thread#interrupt 411 */ 412 public final void interrupt() { 413 synchronized (threadRefs) { 414 for (Thread thread : threads) { 415 thread.interrupt(); 416 } 417 } 418 synchronized (groups) { 419 for (ThreadGroup group : groups) { 420 group.interrupt(); 421 } 422 } 423 } 424 425 /** 426 * Checks whether this thread group is a daemon {@code ThreadGroup}. 427 * 428 * @return true if this thread group is a daemon {@code ThreadGroup} 429 * 430 * @see #setDaemon 431 * @see #destroy 432 */ 433 public final boolean isDaemon() { 434 return isDaemon; 435 } 436 437 /** 438 * Checks whether this thread group has already been destroyed. 439 * 440 * @return true if this thread group has already been destroyed 441 * @see #destroy 442 */ 443 public synchronized boolean isDestroyed() { 444 return isDestroyed; 445 } 446 447 /** 448 * Outputs to {@code System.out} a text representation of the 449 * hierarchy of {@code Thread}s and {@code ThreadGroup}s in this thread group (and recursively). 450 * Proper indentation is used to show the nesting of groups inside groups 451 * and threads inside groups. 452 */ 453 public void list() { 454 // We start in a fresh line 455 System.out.println(); 456 list(0); 457 } 458 459 /* 460 * Outputs to {@code System.out}a text representation of the 461 * hierarchy of Threads and ThreadGroups in this thread group (and recursively). 462 * The indentation will be four spaces per level of nesting. 463 * 464 * @param levels How many levels of nesting, so that proper indentation can 465 * be output. 466 */ 467 private void list(int levels) { 468 indent(levels); 469 System.out.println(this.toString()); 470 471 ++levels; 472 synchronized (threadRefs) { 473 for (Thread thread : threads) { 474 indent(levels); 475 System.out.println(thread); 476 } 477 } 478 synchronized (groups) { 479 for (ThreadGroup group : groups) { 480 group.list(levels); 481 } 482 } 483 } 484 485 private void indent(int levels) { 486 for (int i = 0; i < levels; i++) { 487 System.out.print(" "); // 4 spaces for each level 488 } 489 } 490 491 /** 492 * Checks whether this thread group is a direct or indirect parent group of a 493 * given {@code ThreadGroup}. 494 * 495 * @param g the potential child {@code ThreadGroup} 496 * @return true if this thread group is parent of {@code g} 497 */ 498 public final boolean parentOf(ThreadGroup g) { 499 while (g != null) { 500 if (this == g) { 501 return true; 502 } 503 g = g.parent; 504 } 505 return false; 506 } 507 508 /** 509 * Removes an immediate subgroup. 510 * 511 * @param g ThreadGroup to remove 512 * 513 * @see #add(Thread) 514 * @see #add(ThreadGroup) 515 */ 516 private void remove(ThreadGroup g) { 517 synchronized (groups) { 518 for (Iterator<ThreadGroup> i = groups.iterator(); i.hasNext(); ) { 519 ThreadGroup threadGroup = i.next(); 520 if (threadGroup.equals(g)) { 521 i.remove(); 522 break; 523 } 524 } 525 } 526 destroyIfEmptyDaemon(); 527 } 528 529 /** 530 * Resumes every thread in this group and recursively in all its 531 * subgroups. 532 * 533 * @see Thread#resume 534 * @see #suspend 535 * 536 * @deprecated Requires deprecated method Thread.resume(). 537 */ 538 @SuppressWarnings("deprecation") 539 @Deprecated 540 public final void resume() { 541 synchronized (threadRefs) { 542 for (Thread thread : threads) { 543 thread.resume(); 544 } 545 } 546 synchronized (groups) { 547 for (ThreadGroup group : groups) { 548 group.resume(); 549 } 550 } 551 } 552 553 /** 554 * Sets whether this is a daemon {@code ThreadGroup} or not. Daemon 555 * thread groups are automatically destroyed when they become empty. 556 * 557 * @param isDaemon the new value 558 * @see #isDaemon 559 * @see #destroy 560 */ 561 public final void setDaemon(boolean isDaemon) { 562 this.isDaemon = isDaemon; 563 } 564 565 /** 566 * Configures the maximum allowed priority for a {@code Thread} in this group and 567 * recursively in all its subgroups. 568 * 569 * <p>A caller can never increase the maximum priority of a thread group. 570 * Such an attempt will not result in an exception, it will 571 * simply leave the thread group with its current maximum priority. 572 * 573 * @param newMax the new maximum priority to be set 574 * 575 * @throws IllegalArgumentException if the new priority is greater than 576 * Thread.MAX_PRIORITY or less than Thread.MIN_PRIORITY 577 * 578 * @see #getMaxPriority 579 */ 580 public final void setMaxPriority(int newMax) { 581 if (newMax <= this.maxPriority) { 582 if (newMax < Thread.MIN_PRIORITY) { 583 newMax = Thread.MIN_PRIORITY; 584 } 585 586 int parentPriority = parent == null ? newMax : parent.getMaxPriority(); 587 this.maxPriority = parentPriority <= newMax ? parentPriority : newMax; 588 synchronized (groups) { 589 for (ThreadGroup group : groups) { 590 group.setMaxPriority(newMax); 591 } 592 } 593 } 594 } 595 596 /** 597 * Stops every thread in this group and recursively in all its subgroups. 598 * 599 * @see Thread#stop() 600 * @see Thread#stop(Throwable) 601 * @see ThreadDeath 602 * 603 * @deprecated Requires deprecated method Thread.stop(). 604 */ 605 @SuppressWarnings("deprecation") 606 @Deprecated 607 public final void stop() { 608 if (stopHelper()) { 609 Thread.currentThread().stop(); 610 } 611 } 612 613 @SuppressWarnings("deprecation") 614 private boolean stopHelper() { 615 boolean stopCurrent = false; 616 synchronized (threadRefs) { 617 Thread current = Thread.currentThread(); 618 for (Thread thread : threads) { 619 if (thread == current) { 620 stopCurrent = true; 621 } else { 622 thread.stop(); 623 } 624 } 625 } 626 synchronized (groups) { 627 for (ThreadGroup group : groups) { 628 stopCurrent |= group.stopHelper(); 629 } 630 } 631 return stopCurrent; 632 } 633 634 /** 635 * Suspends every thread in this group and recursively in all its 636 * subgroups. 637 * 638 * @see Thread#suspend 639 * @see #resume 640 * 641 * @deprecated Requires deprecated method Thread.suspend(). 642 */ 643 @SuppressWarnings("deprecation") 644 @Deprecated 645 public final void suspend() { 646 if (suspendHelper()) { 647 Thread.currentThread().suspend(); 648 } 649 } 650 651 @SuppressWarnings("deprecation") 652 private boolean suspendHelper() { 653 boolean suspendCurrent = false; 654 synchronized (threadRefs) { 655 Thread current = Thread.currentThread(); 656 for (Thread thread : threads) { 657 if (thread == current) { 658 suspendCurrent = true; 659 } else { 660 thread.suspend(); 661 } 662 } 663 } 664 synchronized (groups) { 665 for (ThreadGroup group : groups) { 666 suspendCurrent |= group.suspendHelper(); 667 } 668 } 669 return suspendCurrent; 670 } 671 672 @Override 673 public String toString() { 674 return getClass().getName() + "[name=" + getName() 675 + ",maxPriority=" + getMaxPriority() + "]"; 676 } 677 678 /** 679 * Handles uncaught exceptions. Any uncaught exception in any {@code Thread} 680 * is forwarded to the thread's {@code ThreadGroup} by invoking this 681 * method. 682 * 683 * <p>New code should use {@link Thread#setUncaughtExceptionHandler} instead of thread groups. 684 * 685 * @param t the Thread that terminated with an uncaught exception 686 * @param e the uncaught exception itself 687 */ 688 public void uncaughtException(Thread t, Throwable e) { 689 if (parent != null) { 690 parent.uncaughtException(t, e); 691 } else if (Thread.getDefaultUncaughtExceptionHandler() != null) { 692 // TODO The spec is unclear regarding this. What do we do? 693 Thread.getDefaultUncaughtExceptionHandler().uncaughtException(t, e); 694 } else if (!(e instanceof ThreadDeath)) { 695 // No parent group, has to be 'system' Thread Group 696 e.printStackTrace(System.err); 697 } 698 } 699 700 /** 701 * Called by the Thread constructor. 702 */ 703 final void addThread(Thread thread) throws IllegalThreadStateException { 704 synchronized (threadRefs) { 705 if (isDestroyed) { 706 throw new IllegalThreadStateException(); 707 } 708 threadRefs.add(new WeakReference<Thread>(thread)); 709 } 710 } 711 712 /** 713 * Called by the VM when a Thread dies. 714 */ 715 final void removeThread(Thread thread) throws IllegalThreadStateException { 716 synchronized (threadRefs) { 717 for (Iterator<Thread> i = threads.iterator(); i.hasNext(); ) { 718 if (i.next().equals(thread)) { 719 i.remove(); 720 break; 721 } 722 } 723 } 724 destroyIfEmptyDaemon(); 725 } 726 }
VMThread編程
1 /* VMThread -- VM interface for Thread of executable code 2 Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation 3 4 This file is part of GNU Classpath. 5 6 GNU Classpath is free software; you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation; either version 2, or (at your option) 9 any later version. 10 11 GNU Classpath is distributed in the hope that it will be useful, but 12 WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with GNU Classpath; see the file COPYING. If not, write to the 18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 19 02110-1301 USA. 20 21 Linking this library statically or dynamically with other modules is 22 making a combined work based on this library. Thus, the terms and 23 conditions of the GNU General Public License cover the whole 24 combination. 25 26 As a special exception, the copyright holders of this library give you 27 permission to link this library with independent modules to produce an 28 executable, regardless of the license terms of these independent 29 modules, and to copy and distribute the resulting executable under 30 terms of your choice, provided that you also meet, for each linked 31 independent module, the terms and conditions of the license of that 32 module. An independent module is a module which is not derived from 33 or based on this library. If you modify this library, you may extend 34 this exception to your version of the library, but you are not 35 obligated to do so. If you do not wish to do so, delete this 36 exception statement from your version. */ 37 38 package java.lang; 39 40 /** 41 * VM interface for Thread of executable code. Holds VM dependent state. 42 * It is deliberately package local and final and should only be accessed 43 * by the Thread class. 44 * <p> 45 * This is the GNU Classpath reference implementation, it should be adapted 46 * for a specific VM. 47 * <p> 48 * The following methods must be implemented: 49 * <ul> 50 * <li>native void start(long stacksize); 51 * <li>native void interrupt(); 52 * <li>native boolean isInterrupted(); 53 * <li>native void suspend(); 54 * <li>native void resume(); 55 * <li>native void nativeSetPriority(int priority); 56 * <li>native void nativeStop(Throwable t); 57 * <li>native static Thread currentThread(); 58 * <li>static native void yield(); 59 * <li>static native boolean interrupted(); 60 * </ul> 61 * All other methods may be implemented to make Thread handling more efficient 62 * or to implement some optional (and sometimes deprecated) behaviour. Default 63 * implementations are provided but it is highly recommended to optimize them 64 * for a specific VM. 65 * 66 * @author Jeroen Frijters (jeroen@frijters.net) 67 * @author Dalibor Topic (robilad@kaffe.org) 68 */ 69 final class VMThread 70 { 71 /** 72 * The Thread object that this VM state belongs to. 73 * Used in currentThread() and start(). 74 * Note: when this thread dies, this reference is *not* cleared 75 */ 76 volatile Thread thread; 77 78 /** 79 * Flag that is set when the thread runs, used by stop() to protect against 80 * stop's getting lost. 81 */ 82 private volatile boolean running; 83 84 /** 85 * VM private data. 86 */ 87 private transient Object vmdata; 88 89 /** 90 * Private constructor, create VMThreads with the static create method. 91 * 92 * @param thread The Thread object that was just created. 93 */ 94 private VMThread(Thread thread) 95 { 96 this.thread = thread; 97 } 98 99 /** 100 * This method is the initial Java code that gets executed when a native 101 * thread starts. It's job is to coordinate with the rest of the VMThread 102 * logic and to start executing user code and afterwards handle clean up. 103 */ 104 private void run() 105 { 106 try 107 { 108 try 109 { 110 running = true; 111 synchronized(thread) 112 { 113 Throwable t = thread.stillborn; 114 if(t != null) 115 { 116 thread.stillborn = null; 117 throw t; 118 } 119 } 120 thread.run(); 121 } 122 catch(Throwable t) 123 { 124 try 125 { 126 Thread.UncaughtExceptionHandler handler; 127 handler = thread.getUncaughtExceptionHandler(); 128 handler.uncaughtException(thread, t); 129 } 130 catch(Throwable ignore) 131 { 132 } 133 } 134 } 135 finally 136 { 137 // Setting runnable to false is partial protection against stop 138 // being called while we're cleaning up. To be safe all code in 139 // VMThread be unstoppable. 140 running = false; 141 thread.die(); 142 synchronized(this) 143 { 144 // release the threads waiting to join us 145 notifyAll(); 146 } 147 } 148 } 149 150 /** 151 * Creates a native Thread. This is called from the start method of Thread. 152 * The Thread is started. 153 * 154 * @param thread The newly created Thread object 155 * @param stacksize Indicates the requested stacksize. Normally zero, 156 * non-zero values indicate requested stack size in bytes but it is up 157 * to the specific VM implementation to interpret them and may be ignored. 158 */ 159 static void create(Thread thread, long stacksize) 160 { 161 VMThread vmThread = new VMThread(thread); 162 vmThread.start(stacksize); 163 thread.vmThread = vmThread; 164 } 165 166 /** 167 * Gets the name of the thread. Usually this is the name field of the 168 * associated Thread object, but some implementation might choose to 169 * return the name of the underlying platform thread. 170 */ 171 String getName() 172 { 173 return thread.name; 174 } 175 176 /** 177 * Set the name of the thread. Usually this sets the name field of the 178 * associated Thread object, but some implementations might choose to 179 * set the name of the underlying platform thread. 180 * @param name The new name 181 */ 182 void setName(String name) 183 { 184 thread.name = name; 185 } 186 187 /** 188 * Set the thread priority field in the associated Thread object and 189 * calls the native method to set the priority of the underlying 190 * platform thread. 191 * @param priority The new priority 192 */ 193 void setPriority(int priority) 194 { 195 thread.priority = priority; 196 nativeSetPriority(priority); 197 } 198 199 /** 200 * Returns the priority. Usually this is the priority field from the 201 * associated Thread object, but some implementation might choose to 202 * return the priority of the underlying platform thread. 203 * @return this Thread's priority 204 */ 205 int getPriority() 206 { 207 return thread.priority; 208 } 209 210 /** 211 * Returns true if the thread is a daemon thread. Usually this is the 212 * daemon field from the associated Thread object, but some 213 * implementation might choose to return the daemon state of the underlying 214 * platform thread. 215 * @return whether this is a daemon Thread or not 216 */ 217 boolean isDaemon() 218 { 219 return thread.daemon; 220 } 221 222 /** 223 * Returns the number of stack frames in this Thread. 224 * Will only be called when when a previous call to suspend() returned true. 225 * 226 * @deprecated unsafe operation 227 */ 228 native int countStackFrames(); 229 230 /** 231 * Wait the specified amount of time for the Thread in question to die. 232 * 233 * <p>Note that 1,000,000 nanoseconds == 1 millisecond, but most VMs do 234 * not offer that fine a grain of timing resolution. Besides, there is 235 * no guarantee that this thread can start up immediately when time expires, 236 * because some other thread may be active. So don't expect real-time 237 * performance. 238 * 239 * @param ms the number of milliseconds to wait, or 0 for forever 240 * @param ns the number of extra nanoseconds to sleep (0-999999) 241 * @throws InterruptedException if the Thread is interrupted; it's 242 * <i>interrupted status</i> will be cleared 243 */ 244 synchronized void join(long ms, int ns) throws InterruptedException 245 { 246 // Round up 247 ms += (ns != 0) ? 1 : 0; 248 249 // Compute end time, but don't overflow 250 long now = System.currentTimeMillis(); 251 long end = now + ms; 252 if (end < now) 253 end = Long.MAX_VALUE; 254 255 // A VM is allowed to return from wait() without notify() having been 256 // called, so we loop to handle possible spurious wakeups. 257 while(thread.vmThread != null) 258 { 259 // We use the VMThread object to wait on, because this is a private 260 // object, so client code cannot call notify on us. 261 wait(ms); 262 if(ms != 0) 263 { 264 now = System.currentTimeMillis(); 265 ms = end - now; 266 if(ms <= 0) 267 { 268 break; 269 } 270 } 271 } 272 } 273 274 /** 275 * Cause this Thread to stop abnormally and throw the specified exception. 276 * If you stop a Thread that has not yet started, the stop is ignored 277 * (contrary to what the JDK documentation says). 278 * <b>WARNING</b>This bypasses Java security, and can throw a checked 279 * exception which the call stack is unprepared to handle. Do not abuse 280 * this power. 281 * 282 * <p>This is inherently unsafe, as it can interrupt synchronized blocks and 283 * leave data in bad states. 284 * 285 * <p><b>NOTE</b> stop() should take care not to stop a thread if it is 286 * executing code in this class. 287 * 288 * @param t the Throwable to throw when the Thread dies 289 * @deprecated unsafe operation, try not to use 290 */ 291 void stop(Throwable t) 292 { 293 // Note: we assume that we own the lock on thread 294 // (i.e. that Thread.stop() is synchronized) 295 if(running) 296 nativeStop(t); 297 else 298 thread.stillborn = t; 299 } 300 301 /** 302 * Create a native thread on the underlying platform and start it executing 303 * on the run method of this object. 304 * @param stacksize the requested size of the native thread stack 305 */ 306 native void start(long stacksize); 307 308 /** 309 * Interrupt this thread. 310 */ 311 native void interrupt(); 312 313 /** 314 * Determine whether this Thread has been interrupted, but leave 315 * the <i>interrupted status</i> alone in the process. 316 * 317 * @return whether the Thread has been interrupted 318 */ 319 native boolean isInterrupted(); 320 321 /** 322 * Suspend this Thread. It will not come back, ever, unless it is resumed. 323 */ 324 native void suspend(); 325 326 /** 327 * Resume this Thread. If the thread is not suspended, this method does 328 * nothing. 329 */ 330 native void resume(); 331 332 /** 333 * Set the priority of the underlying platform thread. 334 * 335 * @param priority the new priority 336 */ 337 native void nativeSetPriority(int priority); 338 339 /** 340 * Asynchronously throw the specified throwable in this Thread. 341 * 342 * @param t the exception to throw 343 */ 344 native void nativeStop(Throwable t); 345 346 /** 347 * Return the Thread object associated with the currently executing 348 * thread. 349 * 350 * @return the currently executing Thread 351 */ 352 static native Thread currentThread(); 353 354 /** 355 * Yield to another thread. The Thread will not lose any locks it holds 356 * during this time. There are no guarantees which thread will be 357 * next to run, and it could even be this one, but most VMs will choose 358 * the highest priority thread that has been waiting longest. 359 */ 360 static native void yield(); 361 362 /** 363 * Suspend the current Thread's execution for the specified amount of 364 * time. The Thread will not lose any locks it has during this time. There 365 * are no guarantees which thread will be next to run, but most VMs will 366 * choose the highest priority thread that has been waiting longest. 367 * 368 * <p>Note that 1,000,000 nanoseconds == 1 millisecond, but most VMs do 369 * not offer that fine a grain of timing resolution. Besides, there is 370 * no guarantee that this thread can start up immediately when time expires, 371 * because some other thread may be active. So don't expect real-time 372 * performance. 373 * 374 * @param ms the number of milliseconds to sleep. 375 * @param ns the number of extra nanoseconds to sleep (0-999999) 376 * @throws InterruptedException if the Thread is (or was) interrupted; 377 * it's <i>interrupted status</i> will be cleared 378 */ 379 static void sleep(long ms, int ns) throws InterruptedException 380 { 381 // Note: JDK treats a zero length sleep is like Thread.yield(), 382 // without checking the interrupted status of the thread. 383 // It's unclear if this is a bug in the implementation or the spec. 384 // See http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6213203 385 if (ms == 0 && ns == 0) 386 { 387 if (Thread.interrupted()) 388 throw new InterruptedException(); 389 return; 390 } 391 392 // Compute end time, but don't overflow 393 long now = System.currentTimeMillis(); 394 long end = now + ms; 395 if (end < now) 396 end = Long.MAX_VALUE; 397 398 // A VM is allowed to return from wait() without notify() having been 399 // called, so we loop to handle possible spurious wakeups. 400 VMThread vt = Thread.currentThread().vmThread; 401 synchronized (vt) 402 { 403 while (true) 404 { 405 vt.wait(ms, ns); 406 now = System.currentTimeMillis(); 407 if (now >= end) 408 break; 409 ms = end - now; 410 ns = 0; 411 } 412 } 413 } 414 415 /** 416 * Determine whether the current Thread has been interrupted, and clear 417 * the <i>interrupted status</i> in the process. 418 * 419 * @return whether the current Thread has been interrupted 420 */ 421 static native boolean interrupted(); 422 423 /** 424 * Checks whether the current thread holds the monitor on a given object. 425 * This allows you to do <code>assert Thread.holdsLock(obj)</code>. 426 * 427 * @param obj the object to check 428 * @return true if the current thread is currently synchronized on obj 429 * @throws NullPointerException if obj is null 430 */ 431 static boolean holdsLock(Object obj) 432 { 433 /* Use obj.notify to check if the current thread holds 434 * the monitor of the object. 435 * If it doesn't, notify will throw an exception. 436 */ 437 try 438 { 439 obj.notify(); 440 // okay, current thread holds lock 441 return true; 442 } 443 catch (IllegalMonitorStateException e) 444 { 445 // it doesn't hold the lock 446 return false; 447 } 448 }
http://docjar.com/docs/api/java/lang/package-index.htmlapi