1 package java.lang; 2 import dalvik.system.VMStack; 3 import java.security.AccessController; 4 import java.util.Map; 5 import java.util.HashMap; 6 import org.apache.harmony.security.fortress.SecurityUtils; 7 public class Thread implements Runnable { 8 private static final int NANOS_PER_MILLI = 1000000; 9 private static class ParkState { 10 private static final int UNPARKED = 1; 11 private static final int PREEMPTIVELY_UNPARKED = 2; 12 private static final int PARKED = 3; 13 } 14 public enum State { 15 NEW, 16 RUNNABLE, 17 BLOCKED, 18 WAITING, 19 TIMED_WAITING, 20 TERMINATED 21 } 22 public final static int MAX_PRIORITY = 10; 23 public final static int MIN_PRIORITY = 1; 24 public final static int NORM_PRIORITY = 5; 25 volatile VMThread vmThread; 26 volatile ThreadGroup group; 27 volatile boolean daemon; 28 volatile String name; 29 volatile int priority; 30 volatile long stackSize; 31 Runnable target;//运行的Runnalbe; 32 private static int count = 0; 33 private long id;//线程ID; 34 ThreadLocal.Values localValues; 35 ThreadLocal.Values inheritableValues; 36 private Runnable interruptAction; 37 private ClassLoader contextClassLoader; 38 private UncaughtExceptionHandler uncaughtHandler; 39 private static UncaughtExceptionHandler defaultUncaughtHandler; 40 boolean hasBeenStarted = false;//是否已经开启; 41 private int parkState = ParkState.UNPARKED; 42 43 /** 44 * 不带参数的构造函数; 45 */ 46 public Thread() { 47 create(null, null, null, 0); 48 } 49 50 /** 51 * 带Runnable的构造函数 52 */ 53 public Thread(Runnable runnable) { 54 create(null, runnable, null, 0); 55 } 56 57 /** 58 * 带Runnable对象和线程名的构造函数; 59 */ 60 public Thread(Runnable runnable, String threadName) { 61 if (threadName == null) { 62 throw new NullPointerException(); 63 } 64 create(null, runnable, threadName, 0); 65 } 66 67 /** 68 * 带线程名的构造函数; 69 */ 70 public Thread(String threadName) { 71 if (threadName == null) { 72 throw new NullPointerException(); 73 } 74 75 create(null, null, threadName, 0); 76 } 77 78 /** 79 * 带线程和Runnable对象的构造函数; 80 */ 81 public Thread(ThreadGroup group, Runnable runnable) { 82 create(group, runnable, null, 0); 83 } 84 public Thread(ThreadGroup group, Runnable runnable, String threadName) { 85 if (threadName == null) { 86 throw new NullPointerException(); 87 } 88 89 create(group, runnable, threadName, 0); 90 } 91 92 /** 93 * //带线程和Runnable对象的构造函数; 94 */ 95 public Thread(ThreadGroup group, String threadName) { 96 if (threadName == null) { 97 throw new NullPointerException(); 98 } 99 100 create(group, null, threadName, 0); 101 } 102 103 public Thread(ThreadGroup group, Runnable runnable, String threadName, long stackSize) { 104 if (threadName == null) { 105 throw new NullPointerException(); 106 } 107 create(group, runnable, threadName, stackSize); 108 } 109 110 Thread(ThreadGroup group, String name, int priority, boolean daemon) { 111 synchronized (Thread.class) { 112 id = ++Thread.count; 113 } 114 //给线程命名; 115 if (name == null) { 116 this.name = "Thread-" + id; 117 } else 118 { 119 this.name = name; 120 } 121 122 if (group == null) { 123 throw new InternalError("group not specified"); 124 } 125 this.group = group; 126 this.target = null; 127 this.stackSize = 0; 128 this.priority = priority; 129 this.daemon = daemon; 130 this.group.addThread(this); 131 } 132 133 134 private void create(ThreadGroup group, Runnable runnable, String threadName, long stackSize) { 135 SecurityManager smgr = System.getSecurityManager(); 136 if (smgr != null) { 137 if (group == null) 138 { 139 group = smgr.getThreadGroup(); 140 } 141 if (getClass() != Thread.class) 142 { 143 Class[] signature = new Class[] { ClassLoader.class 144 }; 145 try { 146 getClass().getDeclaredMethod("getContextClassLoader", signature); 147 smgr.checkPermission(new RuntimePermission("enableContextClassLoaderOverride")); 148 } catch (NoSuchMethodException ex) { 149 // Ignore. Just interested in the method's existence. 150 } 151 try { 152 getClass().getDeclaredMethod("setContextClassLoader", signature); 153 smgr.checkPermission(new RuntimePermission("enableContextClassLoaderOverride")); 154 } catch (NoSuchMethodException ex) { 155 // Ignore. Just interested in the method's existence. 156 } 157 } 158 } 159 /** 160 * 返回一个线程; 161 */ 162 Thread currentThread = Thread.currentThread();//实际调用VMThread.currentThread(); 163 if (group == null) { 164 group = currentThread.getThreadGroup(); 165 } 166 group.checkAccess(); 167 if (group.isDestroyed()) { 168 throw new IllegalThreadStateException("Group already destroyed"); 169 } 170 this.group = group; 171 synchronized (Thread.class) {//同步,设置线程id; 172 id = ++Thread.count; 173 } 174 if (threadName == null) { 175 this.name = "Thread-" + id; 176 } else { 177 this.name = threadName; 178 } 179 this.target = runnable;//注意这里,是关键; 180 this.stackSize = stackSize; 181 this.priority = currentThread.getPriority();//优先级; 182 this.contextClassLoader = currentThread.contextClassLoader; 183 if (currentThread.inheritableValues != null) { 184 inheritableValues 185 = new ThreadLocal.Values(currentThread.inheritableValues); 186 } 187 SecurityUtils.putContext(this, AccessController.getContext()); 188 this.group.addThread(this); 189 } 190 191 /** 192 * 获取当前线程数; 193 */ 194 public static int activeCount() { 195 return currentThread().getThreadGroup().activeCount(); 196 } 197 198 public final void checkAccess() { 199 SecurityManager currentManager = System.getSecurityManager(); 200 if (currentManager != null) { 201 currentManager.checkAccess(this); 202 } 203 } 204 205 @Deprecated 206 public int countStackFrames() { 207 return getStackTrace().length; 208 } 209 210 public static Thread currentThread() { 211 return VMThread.currentThread(); 212 } 213 214 @Deprecated 215 public void destroy() { 216 throw new NoSuchMethodError("Thread.destroy()"); // TODO Externalize??? 217 } 218 219 public static void dumpStack() { 220 new Throwable("stack dump").printStackTrace(); 221 } 222 223 public static int enumerate(Thread[] threads) { 224 Thread thread = Thread.currentThread(); 225 thread.checkAccess(); 226 return thread.getThreadGroup().enumerate(threads); 227 } 228 229 public static Map<Thread, StackTraceElement[]> getAllStackTraces() { 230 SecurityManager securityManager = System.getSecurityManager(); 231 if (securityManager != null) { 232 securityManager.checkPermission(new RuntimePermission("getStackTrace")); 233 securityManager.checkPermission(new RuntimePermission("modifyThreadGroup")); 234 } 235 Map<Thread, StackTraceElement[]> map = new HashMap<Thread, StackTraceElement[]>(); 236 int count = ThreadGroup.mSystem.activeCount(); 237 Thread[] threads = new Thread[count + count / 2]; 238 239 // Enumerate the threads and collect the stacktraces. 240 count = ThreadGroup.mSystem.enumerate(threads); 241 for (int i = 0; i < count; i++) { 242 map.put(threads[i], threads[i].getStackTrace()); 243 } 244 245 return map; 246 } 247 public ClassLoader getContextClassLoader() { 248 SecurityManager sm = System.getSecurityManager(); 249 if (sm != null) { 250 ClassLoader calling = VMStack.getCallingClassLoader(); 251 252 if (calling != null && !calling.isAncestorOf(contextClassLoader)) { 253 sm.checkPermission(new RuntimePermission("getClassLoader")); 254 } 255 } 256 257 return contextClassLoader; 258 } 259 260 public static UncaughtExceptionHandler getDefaultUncaughtExceptionHandler() { 261 return defaultUncaughtHandler; 262 } 263 public long getId() { 264 return id; 265 } 266 267 public final String getName() { 268 return name; 269 } 270 271 public final int getPriority() { 272 return priority; 273 } 274 public StackTraceElement[] getStackTrace() { 275 SecurityManager securityManager = System.getSecurityManager(); 276 if (securityManager != null) { 277 securityManager.checkPermission(new RuntimePermission("getStackTrace")); 278 } 279 280 StackTraceElement ste[] = VMStack.getThreadStackTrace(this); 281 return ste != null ? ste : new StackTraceElement[0]; 282 } 283 284 public State getState() { 285 // TODO This is ugly and should be implemented better. 286 VMThread vmt = this.vmThread; 287 288 // Make sure we have a valid reference to an object. If native code 289 // deletes the reference we won't run into a null reference later. 290 VMThread thread = vmThread; 291 if (thread != null) { 292 // If the Thread Object became invalid or was not yet started, 293 // getStatus() will return -1. 294 int state = thread.getStatus(); 295 if(state != -1) { 296 return VMThread.STATE_MAP[state]; 297 } 298 } 299 return hasBeenStarted ? Thread.State.TERMINATED : Thread.State.NEW; 300 } 301 302 public final ThreadGroup getThreadGroup() { 303 // TODO This should actually be done at native termination. 304 if (getState() == Thread.State.TERMINATED) { 305 return null; 306 } else { 307 return group; 308 } 309 } 310 311 public UncaughtExceptionHandler getUncaughtExceptionHandler() { 312 if (uncaughtHandler != null) 313 return uncaughtHandler; 314 else 315 return group; // ThreadGroup is instance of UEH 316 } 317 318 public void interrupt() { 319 checkAccess(); 320 321 if (interruptAction != null) { 322 interruptAction.run(); 323 } 324 325 VMThread vmt = this.vmThread; 326 if (vmt != null) { 327 vmt.interrupt(); 328 } 329 } 330 331 public static boolean interrupted() { 332 return VMThread.interrupted(); 333 } 334 335 public final boolean isAlive() { 336 return (vmThread != null); 337 } 338 339 public final boolean isDaemon() { 340 return daemon; 341 } 342 343 public boolean isInterrupted() { 344 VMThread vmt = this.vmThread; 345 if (vmt != null) { 346 return vmt.isInterrupted(); 347 } 348 349 return false; 350 } 351 352 //强制等待当前线程执行完成; 353 public final void join() throws InterruptedException { 354 VMThread t = vmThread; 355 if (t == null) { 356 return; 357 } 358 359 synchronized (t) { 360 while (isAlive()) { 361 t.wait(); 362 } 363 } 364 } 365 366 public final void join(long millis) throws InterruptedException { 367 join(millis, 0); 368 } 369 370 public final void join(long millis, int nanos) throws InterruptedException { 371 if (millis < 0 || nanos < 0 || nanos >= NANOS_PER_MILLI) { 372 throw new IllegalArgumentException(); 373 } 374 375 // avoid overflow: if total > 292,277 years, just wait forever 376 boolean overflow = millis >= (Long.MAX_VALUE - nanos) / NANOS_PER_MILLI; 377 boolean forever = (millis | nanos) == 0; 378 if (forever | overflow) { 379 join(); 380 return; 381 } 382 383 VMThread t = vmThread; 384 if (t == null) { 385 return; 386 } 387 388 synchronized (t) { 389 if (!isAlive()) { 390 return; 391 } 392 393 // guaranteed not to overflow 394 long nanosToWait = millis * NANOS_PER_MILLI + nanos; 395 396 // wait until this thread completes or the timeout has elapsed 397 long start = System.nanoTime(); 398 while (true) { 399 t.wait(millis, nanos); 400 if (!isAlive()) { 401 break; 402 } 403 long nanosElapsed = System.nanoTime() - start; 404 long nanosRemaining = nanosToWait - nanosElapsed; 405 if (nanosRemaining <= 0) { 406 break; 407 } 408 millis = nanosRemaining / NANOS_PER_MILLI; 409 nanos = (int) (nanosRemaining - millis * NANOS_PER_MILLI); 410 } 411 } 412 } 413 414 @Deprecated 415 public final void resume() { 416 checkAccess(); 417 VMThread vmt = this.vmThread; 418 if (vmt != null) { 419 vmt.resume(); 420 } 421 } 422 423 //调用目标Ruunable的run方法; 424 public void run() { 425 if (target != null) { 426 target.run(); 427 } 428 } 429 430 public void setContextClassLoader(ClassLoader cl) { 431 SecurityManager securityManager = System.getSecurityManager(); 432 if (securityManager != null) { 433 securityManager.checkPermission(new RuntimePermission("setContextClassLoader")); 434 } 435 436 contextClassLoader = cl; 437 } 438 439 public final void setDaemon(boolean isDaemon) { 440 checkAccess(); 441 442 if (hasBeenStarted) { 443 throw new IllegalThreadStateException("Thread already started."); // TODO Externalize? 444 } 445 446 if (vmThread == null) { 447 daemon = isDaemon; 448 } 449 } 450 451 public static void setDefaultUncaughtExceptionHandler(UncaughtExceptionHandler handler) { 452 SecurityManager securityManager = System.getSecurityManager(); 453 if (securityManager != null) { 454 securityManager.checkPermission(new RuntimePermission ("setDefaultUncaughtExceptionHandler")); 455 } 456 457 Thread.defaultUncaughtHandler = handler; 458 } 459 460 @SuppressWarnings("unused") 461 private void setInterruptAction(Runnable action) { 462 this.interruptAction = action; 463 } 464 465 public final void setName(String threadName) { 466 if (threadName == null) { 467 throw new NullPointerException(); 468 } 469 470 checkAccess(); 471 472 name = threadName; 473 VMThread vmt = this.vmThread; 474 if (vmt != null) { 475 /* notify the VM that the thread name has changed */ 476 vmt.nameChanged(threadName); 477 } 478 } 479 480 public final void setPriority(int priority) { 481 checkAccess(); 482 483 if (priority < Thread.MIN_PRIORITY || priority > Thread.MAX_PRIORITY) { 484 throw new IllegalArgumentException("Prioritiy out of range"); // TODO Externalize? 485 } 486 487 if (priority > group.getMaxPriority()) { 488 priority = group.getMaxPriority(); 489 } 490 491 this.priority = priority; 492 493 VMThread vmt = this.vmThread; 494 if (vmt != null) { 495 vmt.setPriority(priority); 496 } 497 } 498 499 public void setUncaughtExceptionHandler(UncaughtExceptionHandler handler) { 500 checkAccess(); 501 502 uncaughtHandler = handler; 503 } 504 505 506 public static void sleep(long time) throws InterruptedException { 507 Thread.sleep(time, 0); 508 } 509 510 public static void sleep(long millis, int nanos) throws InterruptedException { 511 VMThread.sleep(millis, nanos); 512 } 513 514 public synchronized void start() { 515 if (hasBeenStarted) { 516 throw new IllegalThreadStateException("Thread already started."); // TODO Externalize? 517 } 518 519 hasBeenStarted = true; 520 521 VMThread.create(this, stackSize); 522 } 523 524 525 @Deprecated 526 public final void stop() { 527 stop(new ThreadDeath()); 528 } 529 530 531 @Deprecated 532 public final synchronized void stop(Throwable throwable) { 533 SecurityManager securityManager = System.getSecurityManager(); 534 if (securityManager != null) { 535 securityManager.checkAccess(this); 536 if (Thread.currentThread() != this) { 537 securityManager.checkPermission(new RuntimePermission("stopThread")); 538 } 539 } 540 541 if (throwable == null) { 542 throw new NullPointerException(); 543 } 544 545 VMThread vmt = this.vmThread; 546 if (vmt != null) { 547 vmt.stop(throwable); 548 } 549 } 550 551 552 @Deprecated 553 public final void suspend() { 554 checkAccess(); 555 556 VMThread vmt = this.vmThread; 557 if (vmt != null) { 558 vmt.suspend(); 559 } 560 } 561 562 563 @Override 564 public String toString() { 565 return "Thread[" + name + "," + priority + "," + group.getName() + "]"; 566 } 567 568 public static void yield() { 569 VMThread.yield(); 570 } 571 572 573 574 public static boolean holdsLock(Object object) { 575 return currentThread().vmThread.holdsLock(object); 576 } 577 578 579 public static interface UncaughtExceptionHandler { 580 /** 581 * The thread is being terminated by an uncaught exception. Further 582 * exceptions thrown in this method are prevent the remainder of the 583 * method from executing, but are otherwise ignored. 584 * 585 * @param thread the thread that has an uncaught exception 586 * @param ex the exception that was thrown 587 * 588 * @since Android 1.0 589 */ 590 void uncaughtException(Thread thread, Throwable ex); 591 } 592 593 /** 594 * Implementation of <code>unpark()</code>. See {@link LangAccessImpl}. 595 */ 596 /*package*/ void unpark() { 597 VMThread vmt = vmThread; 598 599 if (vmt == null) { 600 /* 601 * vmThread is null before the thread is start()ed. In 602 * this case, we just go ahead and set the state to 603 * PREEMPTIVELY_UNPARKED. Since this happens before the 604 * thread is started, we don't have to worry about 605 * synchronizing with it. 606 */ 607 parkState = ParkState.PREEMPTIVELY_UNPARKED; 608 return; 609 } 610 611 synchronized (vmt) { 612 switch (parkState) { 613 case ParkState.PREEMPTIVELY_UNPARKED: { 614 /* 615 * Nothing to do in this case: By definition, a 616 * preemptively unparked thread is to remain in 617 * the preemptively unparked state if it is told 618 * to unpark. 619 */ 620 break; 621 } 622 case ParkState.UNPARKED: { 623 parkState = ParkState.PREEMPTIVELY_UNPARKED; 624 break; 625 } 626 default /*parked*/: { 627 parkState = ParkState.UNPARKED; 628 vmt.notifyAll(); 629 break; 630 } 631 } 632 } 633 } 634 635 /*package*/ void parkFor(long nanos) { 636 VMThread vmt = vmThread; 637 638 if (vmt == null) { 639 // Running threads should always have an associated vmThread. 640 throw new AssertionError(); 641 } 642 643 synchronized (vmt) { 644 switch (parkState) { 645 case ParkState.PREEMPTIVELY_UNPARKED: { 646 parkState = ParkState.UNPARKED; 647 break; 648 } 649 case ParkState.UNPARKED: { 650 long millis = nanos / NANOS_PER_MILLI; 651 nanos %= NANOS_PER_MILLI; 652 653 parkState = ParkState.PARKED; 654 try { 655 vmt.wait(millis, (int) nanos); 656 } catch (InterruptedException ex) { 657 interrupt(); 658 } finally { 659 /* 660 * Note: If parkState manages to become 661 * PREEMPTIVELY_UNPARKED before hitting this 662 * code, it should left in that state. 663 */ 664 if (parkState == ParkState.PARKED) { 665 parkState = ParkState.UNPARKED; 666 } 667 } 668 break; 669 } 670 default /*parked*/: { 671 throw new AssertionError( 672 "shouldn't happen: attempt to repark"); 673 } 674 } 675 } 676 } 677 678 /*package*/ void parkUntil(long time) { 679 VMThread vmt = vmThread; 680 681 if (vmt == null) { 682 // Running threads should always have an associated vmThread. 683 throw new AssertionError(); 684 } 685 686 synchronized (vmt) { 687 /* 688 * Note: This conflates the two time bases of "wall clock" 689 * time and "monotonic uptime" time. However, given that 690 * the underlying system can only wait on monotonic time, 691 * it is unclear if there is any way to avoid the 692 * conflation. The downside here is that if, having 693 * calculated the delay, the wall clock gets moved ahead, 694 * this method may not return until well after the wall 695 * clock has reached the originally designated time. The 696 * reverse problem (the wall clock being turned back) 697 * isn't a big deal, since this method is allowed to 698 * spuriously return for any reason, and this situation 699 * can safely be construed as just such a spurious return. 700 */ 701 long delayMillis = time - System.currentTimeMillis(); 702 703 if (delayMillis <= 0) { 704 parkState = ParkState.UNPARKED; 705 } else { 706 parkFor(delayMillis * NANOS_PER_MILLI); 707 } 708 } 709 } 710 }