java thread programming_Programming for thread in Java

1 packagejava.lang;2 importdalvik.system.VMStack;3 importjava.util.ArrayList;4 importjava.util.HashMap;5 importjava.util.List;6 importjava.util.Map;7 importlibcore.util.EmptyArray;8

9 /**

10 * A {@codeThread} is a concurrent unit of execution. It has its own call stack11 * for methods being invoked, their arguments and local variables. Each virtual12 * machine instance has at least one main {@codeThread} running when it is13 * started; typically, there are several others for housekeeping. The14 * application might decide to launch additional {@codeThread}s for specific15 * purposes.16 *

17 * {@codeThread}s in the same VM interact and synchronize by the use of shared18 * objects and monitors associated with these objects. Synchronized methods and19 * part of the API in {@linkObject} also allow {@codeThread}s to cooperate.20 *

21 * There are basically two main ways of having a {@codeThread} execute22 * application code. One is providing a new class that extends {@codeThread}23 * and overriding its {@link#run()} method. The other is providing a new24 * {@codeThread} instance with a {@linkRunnable} object during its creation.25 * In both cases, the {@link#start()} method must be called to actually execute26 * the new {@codeThread}.27 *

28 * Each {@codeThread} has an integer priority that basically determines the29 * amount of CPU time the {@codeThread} gets. It can be set using the30 * {@link#setPriority(int)} method. A {@codeThread} can also be made a daemon,31 * which makes it run in the background. The latter also affects VM termination32 * behavior: the VM does not terminate automatically as long as there are33 * non-daemon threads running.34 *35 *@seejava.lang.Object36 *@seejava.lang.ThreadGroup37 *38 */

39 public class Thread implementsRunnable {40 private static final int NANOS_PER_MILLI = 1000000;41

42 /**Park states*/

43 private static classParkState {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 one53 * state at a time.54 */

55 public enumState {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 TERMINATED80 }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 volatileVMThread vmThread;95 volatileThreadGroup group;96 volatile booleandaemon;97 volatileString name;98 volatile intpriority;99 volatile longstackSize;100 Runnable target;101 private static int count = 0;102 /**

103 * Holds the thread's ID. We simply count upwards, so104 * each Thread has a unique ID.105 */

106 private longid;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 interruptActions = new ArrayList();117 /**

118 * Holds the class loader for this Thread, in case there is one.119 */

120 privateClassLoader contextClassLoader;121 /**

122 * Holds the handler for uncaught exceptions in this Thread,123 * in case there is one.124 */

125 privateUncaughtExceptionHandler uncaughtHandler;126 /**

127 * Holds the default handler for uncaught exceptions, in case there is one.128 */

129 private staticUncaughtExceptionHandler defaultUncaughtHandler;130 /**

131 * Reflects whether this Thread has already been started. A Thread132 * can only be started once (no recycling). Also, we need it to deduce133 * 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 privateObject parkBlocker;142

143 /**

144 * Constructs a new {@codeThread} with no {@codeRunnable} object and a145 * newly generated name. The new {@codeThread} will belong to the same146 * {@codeThreadGroup} as the {@codeThread} calling this constructor.147 *148 *@seejava.lang.ThreadGroup149 *@seejava.lang.Runnable150 */

151 publicThread() {152 create(null, null, null, 0);153 }154 /**

155 * Constructs a new {@codeThread} with a {@codeRunnable} object and a156 * newly generated name. The new {@codeThread} will belong to the same157 * {@codeThreadGroup} as the {@codeThread} calling this constructor.158 *159 *@paramrunnable160 * a {@codeRunnable} whose method run will be161 * executed by the new {@codeThread}162 *163 *@seejava.lang.ThreadGroup164 *@seejava.lang.Runnable165 */

166 publicThread(Runnable runnable) {167 create(null, runnable, null, 0);168 }169

170 /**

171 * Constructs a new {@codeThread} with a {@codeRunnable} object and name172 * provided. The new {@codeThread} will belong to the same {@code

173 * ThreadGroup} as the {@codeThread} calling this constructor.174 *175 *@paramrunnable176 * a {@codeRunnable} whose method run will be177 * executed by the new {@codeThread}178 *@paramthreadName179 * the name for the {@codeThread} being created180 *181 *@seejava.lang.ThreadGroup182 *@seejava.lang.Runnable183 */

184 publicThread(Runnable runnable, String threadName) {185 if (threadName == null) {186 throw newNullPointerException();187 }188

189 create(null, runnable, threadName, 0);190 }191

192 /**

193 * Constructs a new {@codeThread} with no {@codeRunnable} object and the194 * name provided. The new {@codeThread} will belong to the same {@code

195 * ThreadGroup} as the {@codeThread} calling this constructor.196 *197 *@paramthreadName198 * the name for the {@codeThread} being created199 *200 *@seejava.lang.ThreadGroup201 *@seejava.lang.Runnable202 *203 */

204 publicThread(String threadName) {205 if (threadName == null) {206 throw newNullPointerException();207 }208

209 create(null, null, threadName, 0);210 }211

212 /**

213 * Constructs a new {@codeThread} with a {@codeRunnable} object and a214 * newly generated name. The new {@codeThread} will belong to the {@code

215 * ThreadGroup} passed as parameter.216 *217 *@paramgroup218 * {@codeThreadGroup} to which the new {@codeThread} will219 * belong220 *@paramrunnable221 * a {@codeRunnable} whose method run will be222 * executed by the new {@codeThread}223 *@throwsIllegalThreadStateException224 * if group.destroy() has already been done225 *@seejava.lang.ThreadGroup226 *@seejava.lang.Runnable227 */

228 publicThread(ThreadGroup group, Runnable runnable) {229 create(group, runnable, null, 0);230 }231

232 /**

233 * Constructs a new {@codeThread} with a {@codeRunnable} object, the given234 * name and belonging to the {@codeThreadGroup} passed as parameter.235 *236 *@paramgroup237 * ThreadGroup to which the new {@codeThread} will belong238 *@paramrunnable239 * a {@codeRunnable} whose method run will be240 * executed by the new {@codeThread}241 *@paramthreadName242 * the name for the {@codeThread} being created243 *@throwsIllegalThreadStateException244 * if group.destroy() has already been done245 *@seejava.lang.ThreadGroup246 *@seejava.lang.Runnable247 */

248 publicThread(ThreadGroup group, Runnable runnable, String threadName) {249 if (threadName == null) {250 throw newNullPointerException();251 }252

253 create(group, runnable, threadName, 0);254 }255

256 /**

257 * Constructs a new {@codeThread} with no {@codeRunnable} object, the258 * given name and belonging to the {@codeThreadGroup} passed as parameter.259 *260 *@paramgroup261 * {@codeThreadGroup} to which the new {@codeThread} will belong262 *@paramthreadName263 * the name for the {@codeThread} being created264 *@throwsIllegalThreadStateException265 * if group.destroy() has already been done266 *@seejava.lang.ThreadGroup267 *@seejava.lang.Runnable268 */

269 publicThread(ThreadGroup group, String threadName) {270 if (threadName == null) {271 throw newNullPointerException();272 }273

274 create(group, null, threadName, 0);275 }276

277 /**

278 * Constructs a new {@codeThread} with a {@codeRunnable} object, the given279 * name and belonging to the {@codeThreadGroup} passed as parameter.280 *281 *@paramgroup282 * {@codeThreadGroup} to which the new {@codeThread} will283 * belong284 *@paramrunnable285 * a {@codeRunnable} whose method run will be286 * executed by the new {@codeThread}287 *@paramthreadName288 * the name for the {@codeThread} being created289 *@paramstackSize290 * a stack size for the new {@codeThread}. This has a highly291 * platform-dependent interpretation. It may even be ignored292 * completely.293 *@throwsIllegalThreadStateException294 * if group.destroy() has already been done295 *@seejava.lang.ThreadGroup296 *@seejava.lang.Runnable297 */

298 public Thread(ThreadGroup group, Runnable runnable, String threadName, longstackSize) {299 if (threadName == null) {300 throw newNullPointerException();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 such310 * a thing (e.g. for Main).311 */

312 Thread(ThreadGroup group, String name, int priority, booleandaemon) {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 their342 * work to.343 *344 *@paramgroup ThreadGroup to which the new Thread will belong345 *@paramrunnable a java.lang.Runnable whose method run will346 * be executed by the new Thread347 *@paramthreadName Name for the Thread being created348 *@paramstackSize Platform dependent stack size349 *@throwsIllegalThreadStateException if group.destroy() has350 * already been done351 *@seejava.lang.ThreadGroup352 *@seejava.lang.Runnable353 */

354 private void create(ThreadGroup group, Runnable runnable, String threadName, longstackSize) {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 = newThreadLocal.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 {@codeThread}s in the running {@code

394 * Thread}'s group and its subgroups.395 *396 *@returnthe number of {@codeThread}s397 */

398 public static intactiveCount() {399 returncurrentThread().getThreadGroup().activeCount();400 }401

402 /**

403 * Does nothing.404 */

405 public final voidcheckAccess() {406 }407

408 /**

409 * Returns the number of stack frames in this thread.410 *411 *@returnNumber of stack frames412 *@deprecatedThe results of this call were never well defined. To make413 * things worse, it would depend on whether the Thread was414 * suspended or not, and suspend was deprecated too.415 */

416 @Deprecated417 public intcountStackFrames() {418 returngetStackTrace().length;419 }420

421 /**

422 * Returns the Thread of the caller, that is, the current Thread.423 *424 *@returnthe current Thread.425 */

426 public staticThread currentThread() {427 returnVMThread.currentThread();428 }429

430 /**

431 * Destroys the receiver without any monitor cleanup.432 *433 *@deprecatedNot implemented.434 */

435 @Deprecated436 public voiddestroy() {437 throw new NoSuchMethodError("Thread.destroy()"); //TODO Externalize???

438 }439

440 /**

441 * Prints to the standard error stream a text representation of the current442 * stack for this Thread.443 *444 *@seeThrowable#printStackTrace()445 */

446 public static voiddumpStack() {447 new Throwable("stack dump").printStackTrace();448 }449

450 /**

451 * Copies an array with all Threads which are in the same ThreadGroup as the452 * receiver - and subgroups - into the array threads passed as453 * parameter. If the array passed as parameter is too small no exception is454 * thrown - the extra elements are simply not copied.455 *456 *@paramthreads457 * array into which the Threads will be copied458 *@returnHow many Threads were copied over459 */

460 public static intenumerate(Thread[] threads) {461 Thread thread =Thread.currentThread();462 returnthread.getThreadGroup().enumerate(threads);463 }464

465 /**

466 * Returns a map of all the currently live threads to their stack traces.467 */

468 public static MapgetAllStackTraces() {469 Map map = new HashMap();470

471 //Find out how many live threads we have. Allocate a bit more472 //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 returnmap;483 }484

485 /**

486 * Returns the context ClassLoader for this Thread.487 *488 *@returnClassLoader The context ClassLoader489 *@seejava.lang.ClassLoader490 *@see#getContextClassLoader()491 */

492 publicClassLoader getContextClassLoader() {493 returncontextClassLoader;494 }495

496 /**

497 * Returns the default exception handler that's executed when uncaught498 * exception terminates a thread.499 *500 *@returnan {@linkUncaughtExceptionHandler} or null if501 * none exists.502 */

503 public staticUncaughtExceptionHandler getDefaultUncaughtExceptionHandler() {504 returndefaultUncaughtHandler;505 }506

507 /**

508 * Returns the thread's identifier. The ID is a positive long509 * generated on thread creation, is unique to the thread, and doesn't change510 * during the lifetime of the thread; the ID may be reused after the thread511 * has been terminated.512 *513 *@returnthe thread's ID.514 */

515 public longgetId() {516 returnid;517 }518

519 /**

520 * Returns the name of the Thread.521 *522 *@returnthe Thread's name523 */

524 public finalString getName() {525 returnname;526 }527

528 /**

529 * Returns the priority of the Thread.530 *531 *@returnthe Thread's priority532 *@seeThread#setPriority533 */

534 public final intgetPriority() {535 returnpriority;536 }537

538 /**

539 * Returns an array of {@linkStackTraceElement} representing the current thread's stack.540 */

541 publicStackTraceElement[] 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 for548 * monitoring purposes.549 *550 *@returna {@linkState} value.551 */

552 publicState 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 code557 //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 returnVMThread.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 *@returnthe Thread's ThreadGroup574 */

575 public finalThreadGroup getThreadGroup() {576 //TODO This should actually be done at native termination.

577 if (getState() ==Thread.State.TERMINATED) {578 return null;579 } else{580 returngroup;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 null is returned.588 *589 *@returnan {@linkUncaughtExceptionHandler} instance or {@codenull}.590 */

591 publicUncaughtExceptionHandler getUncaughtExceptionHandler() {592 if (uncaughtHandler != null)593 returnuncaughtHandler;594 else

595 return group; //ThreadGroup is instance of UEH

596 }597

598 /**

599 * Posts an interrupt request to this {@codeThread}. The behavior depends on600 * the state of this {@codeThread}:601 *

  • 602 *
  • 603 * {@codeThread}s blocked in one of {@codeObject}'s {@codewait()} methods604 * or one of {@codeThread}'s {@codejoin()} or {@codesleep()} methods will605 * be woken up, their interrupt status will be cleared, and they receive an606 * {@linkInterruptedException}.607 *
  • 608 * {@codeThread}s blocked in an I/O operation of an609 * {@linkjava.nio.channels.InterruptibleChannel} will have their interrupt610 * status set and receive an611 * {@linkjava.nio.channels.ClosedByInterruptException}. Also, the channel612 * will be closed.613 *
  • 614 * {@codeThread}s blocked in a {@linkjava.nio.channels.Selector} will have615 * their interrupt status set and return immediately. They don't receive an616 * exception in this case.617 *
    • 618 *619 *@seeThread#interrupted620 *@seeThread#isInterrupted621 */

    622 public voidinterrupt() {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 boolean indicating whether the current Thread (637 * currentThread()) has a pending interrupt request (638 * true) or not (false). It also has the side-effect of639 * clearing the flag.640 *641 *@returna boolean indicating the interrupt status642 *@seeThread#currentThread643 *@seeThread#interrupt644 *@seeThread#isInterrupted645 */

    646 public static booleaninterrupted() {647 returnVMThread.interrupted();648 }649

    650 /**

    651 * Returns true if the receiver has already been started and652 * still runs code (hasn't died yet). Returns false either if653 * the receiver hasn't been started yet or if it has already started and run654 * to completion and died.655 *656 *@returna boolean indicating the liveness of the Thread657 *@seeThread#start658 */

    659 public final booleanisAlive() {660 return (vmThread != null);661 }662

    663 /**

    664 * Returns a boolean indicating whether the receiver is a665 * daemon Thread (true) or not (false) A666 * 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 if668 * it had daemon Threads still running or not.669 *670 *@returna boolean indicating whether the Thread is a daemon671 *@seeThread#setDaemon672 */

    673 public final booleanisDaemon() {674 returndaemon;675 }676

    677 /**

    678 * Returns a boolean indicating whether the receiver has a679 * pending interrupt request (true) or not (680 * false)681 *682 *@returna boolean indicating the interrupt status683 *@seeThread#interrupt684 *@seeThread#interrupted685 */

    686 public booleanisInterrupted() {687 VMThread vmt = this.vmThread;688 if (vmt != null) {689 returnvmt.isInterrupted();690 }691

    692 return false;693 }694

    695 /**

    696 * Blocks the current Thread (Thread.currentThread()) until697 * the receiver finishes its execution and dies.698 *699 *@throwsInterruptedException if interrupt() was called for700 * the receiver while it was in the join() call701 *@seeObject#notifyAll702 *@seejava.lang.ThreadDeath703 */

    704 public final void join() throwsInterruptedException {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 (Thread.currentThread()) until719 * the receiver finishes its execution and dies or the specified timeout720 * expires, whatever happens first.721 *722 *@parammillis The maximum time to wait (in milliseconds).723 *@throwsInterruptedException if interrupt() was called for724 * the receiver while it was in the join() call725 *@seeObject#notifyAll726 *@seejava.lang.ThreadDeath727 */

    728 public final void join(long millis) throwsInterruptedException {729 join(millis, 0);730 }731

    732 /**

    733 * Blocks the current Thread (Thread.currentThread()) until734 * the receiver finishes its execution and dies or the specified timeout735 * expires, whatever happens first.736 *737 *@parammillis The maximum time to wait (in milliseconds).738 *@paramnanos Extra nanosecond precision739 *@throwsInterruptedException if interrupt() was called for740 * the receiver while it was in the join() call741 *@seeObject#notifyAll742 *@seejava.lang.ThreadDeath743 */

    744 public final void join(long millis, int nanos) throwsInterruptedException {745 if (millis < 0 || nanos < 0 || nanos >=NANOS_PER_MILLI) {746 throw newIllegalArgumentException();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 {@codeUnsupportedOperationException}.790 *791 *@seeThread#suspend()792 *@deprecatedUsed with deprecated method {@linkThread#suspend}793 */

    794 @Deprecated795 public final voidresume() {796 throw newUnsupportedOperationException();797 }798

    799 /**

    800 * Calls the run() method of the Runnable object the receiver801 * holds. If no Runnable is set, does nothing.802 *803 *@seeThread#start804 */

    805 public voidrun() {806 if (target != null) {807 target.run();808 }809 }810

    811 /**

    812 * Set the context ClassLoader for the receiver.813 *814 *@paramcl The context ClassLoader815 *@see#getContextClassLoader()816 */

    817 public voidsetContextClassLoader(ClassLoader cl) {818 contextClassLoader =cl;819 }820

    821 /**

    822 * Set if the receiver is a daemon Thread or not. This can only be done823 * before the Thread starts running.824 *825 *@paramisDaemon826 * indicates whether the Thread should be daemon or not827 *@seeThread#isDaemon828 */

    829 public final void setDaemon(booleanisDaemon) {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 in841 * case any Thread dies due to an unhandled exception.842 *843 *@paramhandler844 * The handler to set or null.845 */

    846 public static voidsetDefaultUncaughtExceptionHandler(UncaughtExceptionHandler handler) {847 Thread.defaultUncaughtHandler =handler;848 }849

    850 /**

    851 * Adds a runnable to be invoked upon interruption. If this thread has852 * already been interrupted, the runnable will be invoked immediately. The853 * action should be idempotent as it may be invoked multiple times for a854 * single interruption.855 *856 *

    Each call to this method must be matched with a corresponding call to857 * {@link#popInterruptAction$}.858 *859 * @hide used by NIO860 */

    861 public final voidpushInterruptAction$(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 {@codeinterruptAction} so it is not invoked upon interruption.873 *874 *@paraminterruptAction the pushed action, used to check that the call875 * stack is correctly nested.876 *877 * @hide used by NIO878 */

    879 public final voidpopInterruptAction$(Runnable interruptAction) {880 synchronized(interruptActions) {881 Runnable removed = interruptActions.remove(interruptActions.size() - 1);882 if (interruptAction !=removed) {883 throw newIllegalArgumentException(884 "Expected " + interruptAction + " but was " +removed);885 }886 }887 }888

    889 /**

    890 * Sets the name of the Thread.891 *892 *@paramthreadName the new name for the Thread893 *@seeThread#getName894 */

    895 public final voidsetName(String threadName) {896 if (threadName == null) {897 throw newNullPointerException();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 not910 * be the parameter that was passed - it will depend on the receiver's911 * ThreadGroup. The priority cannot be set to be higher than the receiver's912 * ThreadGroup's maxPriority().913 *914 *@parampriority915 * new priority for the Thread916 *@throwsIllegalArgumentException917 * if the new priority is greater than Thread.MAX_PRIORITY or918 * less than Thread.MIN_PRIORITY919 *@seeThread#getPriority920 */

    921 public final void setPriority(intpriority) {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 *

    940 * Sets the uncaught exception handler. This handler is invoked in case this941 * Thread dies due to an unhandled exception.942 *

    943 *944 *@paramhandler945 * The handler to set or null.946 */

    947 public voidsetUncaughtExceptionHandler(UncaughtExceptionHandler handler) {948 uncaughtHandler =handler;949 }950

    951 /**

    952 * Causes the thread which sent this message to sleep for the given interval953 * of time (given in milliseconds). The precision is not guaranteed - the954 * Thread may sleep more or less than requested.955 *956 *@paramtime957 * The time to sleep in milliseconds.958 *@throwsInterruptedException959 * if interrupt() was called for this Thread while960 * it was sleeping961 *@seeThread#interrupt()962 */

    963 public static void sleep(long time) throwsInterruptedException {964 Thread.sleep(time, 0);965 }966

    967 /**

    968 * Causes the thread which sent this message to sleep for the given interval969 * of time (given in milliseconds and nanoseconds). The precision is not970 * guaranteed - the Thread may sleep more or less than requested.971 *972 *@parammillis973 * The time to sleep in milliseconds.974 *@paramnanos975 * Extra nanosecond precision976 *@throwsInterruptedException977 * if interrupt() was called for this Thread while978 * it was sleeping979 *@seeThread#interrupt()980 */

    981 public static void sleep(long millis, int nanos) throwsInterruptedException {982 VMThread.sleep(millis, nanos);983 }984

    985 /**

    986 * Starts the new Thread of execution. The run() method of987 * the receiver will be called by the receiver Thread itself (and not the988 * Thread calling start()).989 *990 *@throwsIllegalThreadStateException if the Thread has been started before991 *992 *@seeThread#run993 */

    994 public synchronized voidstart() {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 is1006 * resumed if it was suspended and awakened if it was sleeping, so that it1007 * can proceed to throw ThreadDeath.1008 *1009 *@deprecatedbecause stopping a thread in this manner is unsafe and can1010 * leave your application and the VM in an unpredictable state.1011 */

    1012 @Deprecated1013 public final voidstop() {1014 stop(newThreadDeath());1015 }1016

    1017 /**

    1018 * Throws {@codeUnsupportedOperationException}.1019 *1020 *@throwsNullPointerException if throwable() is1021 * null1022 *@deprecatedbecause stopping a thread in this manner is unsafe and can1023 * leave your application and the VM in an unpredictable state.1024 */

    1025 @Deprecated1026 public final synchronized voidstop(Throwable throwable) {1027 throw newUnsupportedOperationException();1028 }1029

    1030 /**

    1031 * Throws {@codeUnsupportedOperationException}.1032 *1033 *@seeThread#resume()1034 *@deprecatedMay cause deadlocks.1035 */

    1036 @Deprecated1037 public final voidsuspend() {1038 throw newUnsupportedOperationException();1039 }1040

    1041 /**

    1042 * Returns a string containing a concise, human-readable description of the1043 * Thread. It includes the Thread's name, priority, and group name.1044 *1045 *@returna printable representation for the receiver.1046 */

    1047 @Override1048 publicString toString() {1049 return "Thread[" + name + "," + priority + "," + group.getName() + "]";1050 }1051

    1052 /**

    1053 * Causes the calling Thread to yield execution time to another Thread that1054 * is ready to run. The actual scheduling is implementation-dependent.1055 */

    1056 public static voidyield() {1057 VMThread.yield();1058 }1059

    1060 /**

    1061 * Indicates whether the current Thread has a monitor lock on the specified1062 * object.1063 *1064 *@paramobject the object to test for the monitor lock1065 *@returntrue if the current thread has a monitor lock on the specified1066 * object; false otherwise1067 */

    1068 public static booleanholdsLock(Object object) {1069 returncurrentThread().vmThread.holdsLock(object);1070 }1071

    1072 /**

    1073 * Implemented by objects that want to handle cases where a thread is being1074 * terminated by an uncaught exception. Upon such termination, the handler1075 * is notified of the terminating thread and causal exception. If there is1076 * no explicit handler set then the thread's group is the default handler.1077 */

    1078 public static interfaceUncaughtExceptionHandler {1079 /**

    1080 * The thread is being terminated by an uncaught exception. Further1081 * exceptions thrown in this method are prevent the remainder of the1082 * method from executing, but are otherwise ignored.1083 *1084 *@paramthread the thread that has an uncaught exception1085 *@paramex the exception that was thrown1086 */

    1087 voiduncaughtException(Thread thread, Throwable ex);1088 }1089

    1090 /**

    1091 * Unparks this thread. This unblocks the thread it if it was1092 * previously parked, or indicates that the thread is "preemptively1093 * unparked" if it wasn't already parked. The latter means that the1094 * next time the thread is told to park, it will merely clear its1095 * latent park bit and carry on without blocking.1096 *1097 *

    See {@linkjava.util.concurrent.locks.LockSupport} for more1098 * in-depth information of the behavior of this method.

    1099 *1100 * @hide for Unsafe1101 */

    1102 public voidunpark() {1103 VMThread vmt =vmThread;1104

    1105 if (vmt == null) {1106 /*

    1107 * vmThread is null before the thread is start()ed. In1108 * this case, we just go ahead and set the state to1109 * PREEMPTIVELY_UNPARKED. Since this happens before the1110 * thread is started, we don't have to worry about1111 * synchronizing with it.1112 */

    1113 parkState =ParkState.PREEMPTIVELY_UNPARKED;1114 return;1115 }1116

    1117 synchronized(vmt) {1118 switch(parkState) {1119 caseParkState.PREEMPTIVELY_UNPARKED: {1120 /*

    1121 * Nothing to do in this case: By definition, a1122 * preemptively unparked thread is to remain in1123 * the preemptively unparked state if it is told1124 * to unpark.1125 */

    1126 break;1127 }1128 caseParkState.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, or1143 * indefinitely. If not indefinitely, this method unparks the thread1144 * after the given number of nanoseconds if no other thread unparks it1145 * first. If the thread has been "preemptively unparked," this method1146 * cancels that unparking and returns immediately. This method may1147 * also return spuriously (that is, without the thread being told to1148 * unpark and without the indicated amount of time elapsing).1149 *1150 *

    See {@linkjava.util.concurrent.locks.LockSupport} for more1151 * in-depth information of the behavior of this method.

    1152 *1153 *

    This method must only be called when this is the current1154 * thread.1155 *1156 *@paramnanos number of nanoseconds to park for or 01157 * to park indefinitely1158 *@throwsIllegalArgumentException thrown if nanos < 01159 *1160 * @hide for Unsafe1161 */

    1162 public void parkFor(longnanos) {1163 VMThread vmt =vmThread;1164

    1165 if (vmt == null) {1166 //Running threads should always have an associated vmThread.

    1167 throw newAssertionError();1168 }1169

    1170 synchronized(vmt) {1171 switch(parkState) {1172 caseParkState.PREEMPTIVELY_UNPARKED: {1173 parkState =ParkState.UNPARKED;1174 break;1175 }1176 caseParkState.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 become1188 * PREEMPTIVELY_UNPARKED before hitting this1189 * 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 newAssertionError(1199 "shouldn't happen: attempt to repark");1200 }1201 }1202 }1203 }1204

    1205 /**

    1206 * Parks the current thread until the specified system time. This1207 * method attempts to unpark the current thread immediately after1208 * System.currentTimeMillis() reaches the specified1209 * value, if no other thread unparks it first. If the thread has1210 * been "preemptively unparked," this method cancels that1211 * unparking and returns immediately. This method may also return1212 * spuriously (that is, without the thread being told to unpark1213 * and without the indicated amount of time elapsing).1214 *1215 *

    See {@linkjava.util.concurrent.locks.LockSupport} for more1216 * in-depth information of the behavior of this method.

    1217 *1218 *

    This method must only be called when this is the1219 * current thread.1220 *1221 *@paramtime the time after which the thread should be unparked,1222 * in absolute milliseconds-since-the-epoch1223 *1224 * @hide for Unsafe1225 */

    1226 public void parkUntil(longtime) {1227 VMThread vmt =vmThread;1228

    1229 if (vmt == null) {1230 //Running threads should always have an associated vmThread.

    1231 throw newAssertionError();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 that1238 * the underlying system can only wait on monotonic time,1239 * it is unclear if there is any way to avoid the1240 * conflation. The downside here is that if, having1241 * calculated the delay, the wall clock gets moved ahead,1242 * this method may not return until well after the wall1243 * clock has reached the originally designated time. The1244 * reverse problem (the wall clock being turned back)1245 * isn't a big deal, since this method is allowed to1246 * spuriously return for any reason, and this situation1247 * 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 }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值