Thread的常见属性

属性 方法 说明
ID getId() 线程的唯一标识,不同线程ID不会重复
名称 getName() 在调试工具中会用到
状态 getState() 表示线程当前状态
优先级 getPriority() 优先级高的线程理论上更容易被调度
是否后台线程 isDaemon() JVM会在一个进程的所有非后台进程结束后,才结束运行
是否存活 isAlive() run方法是否运行结束
(调用考虑点:非运行态不能执行到这行代码,如阻塞态、就绪态)
是否中断 isInterrupted() 线程是否中断

常用方法

start启动线程

  • 启动线程必须调用start()。
  • run方法 和 start方法不同。
  • run() 为线程运行态时所执行任务的方法,如果使用Runnable传入构造创建线程,就执行Runnable对象的run方法。

    interrupt通知停止运行

    通过 thread 对象调用 interrupt() 方法通知该线程停止运行。
    thread 收到通知的方式有两种:

  • 如果线程调用了 wait/join/sleep 等方法而阻塞挂起,则以InterruptedException 异常的形式通知,清除中断标志。

  • 否则,只是内部的一个中断标志被设置,thread 可以通过
    • Thread.interrupted() 判断当前线程的中断标志被设置,清除中断标志。
    • Thread.currentThread().isInterrupted() 判断指定线程的中断标志被设置,不清除中断标志。

第二种方式通知收到的更及时,即使线程正在 sleep 也可以马上收到。

方法 说明
public void interrupt() 中断对象关联的线程,如果线程正在阻塞,则以异常方式通知,否则设置标志位
public static boolean interrupted() 判断当前线程的中断标志位是否设置,调用后清除标志位
public boolean isInterrupted() 判断对象关联的线程的中断标志位是否设置,调用后不清除标志位

join等待一个线程

作用:当前线程(代码行所在线程)阻塞并等待,直到满足条件后,当前线程继续往下执行。
条件:无参时线程的引用对象执行完毕;有参时为引用线程执行完毕或时间耗完。

方法 说明
public void join() 等待线程结束
public void join(long millis) 当前线程阻塞并等待引用线程结束,最多等待 millis 毫秒
public void join(long millis, int nanos) 同理,但精度更高

join方法底层是调用的Object的wait()方法,wait方法会让线程进入阻塞状态,并且会释放线程占有的锁,并交出CPU执行权限。

image.png

在main线程中调用thread.join()方法后,main线程会进入等待,然后等待thread执行完之后再继续执行。

sleep线程休眠

作用:让当前线程,休眠给定的时间。
注意:因为线程的调度是不可控的,所以,这个方法只能保证线程真正休眠时间是大于等于休眠时间的

sleep让线程睡眠,交出CPU,让CPU去执行其他的任务。sleep方法不会释放锁,也就是说如果当前线程持有对某个对象的锁,则即使调用sleep方法,其他线程也无法访问这个对象。sleep方法相当于让线程进入阻塞状态。

yield让出CPU

调用yield方法会让当前线程交出CPU权限,让CPU去执行其他的线程。它跟sleep方法类似,同样不会释放锁。但是yield不能控制具体的交出CPU的时间,另外,yield方法只能让拥有相同优先级的线程有获取CPU执行时间的机会。

注意,调用yield方法并不会让线程进入阻塞状态,而是让线程重回就绪状态,它只需要等待重新获取CPU执行时间,这一点是和sleep方法不一样的。

线程状态

  1. public enum State {
  2. /**
  3. * Thread state for a thread which has not yet started.
  4. */
  5. NEW,
  6. /**
  7. * Thread state for a runnable thread. A thread in the runnable
  8. * state is executing in the Java virtual machine but it may
  9. * be waiting for other resources from the operating system
  10. * such as processor.
  11. */
  12. RUNNABLE,
  13. /**
  14. * Thread state for a thread blocked waiting for a monitor lock.
  15. * A thread in the blocked state is waiting for a monitor lock
  16. * to enter a synchronized block/method or
  17. * reenter a synchronized block/method after calling
  18. * {@link Object#wait() Object.wait}.
  19. */
  20. BLOCKED,
  21. /**
  22. * Thread state for a waiting thread.
  23. * A thread is in the waiting state due to calling one of the
  24. * following methods:
  25. * <ul>
  26. * <li>{@link Object#wait() Object.wait} with no timeout</li>
  27. * <li>{@link #join() Thread.join} with no timeout</li>
  28. * <li>{@link LockSupport#park() LockSupport.park}</li>
  29. * </ul>
  30. *
  31. * <p>A thread in the waiting state is waiting for another thread to
  32. * perform a particular action.
  33. *
  34. * For example, a thread that has called <tt>Object.wait()</tt>
  35. * on an object is waiting for another thread to call
  36. * <tt>Object.notify()</tt> or <tt>Object.notifyAll()</tt> on
  37. * that object. A thread that has called <tt>Thread.join()</tt>
  38. * is waiting for a specified thread to terminate.
  39. */
  40. WAITING,
  41. /**
  42. * Thread state for a waiting thread with a specified waiting time.
  43. * A thread is in the timed waiting state due to calling one of
  44. * the following methods with a specified positive waiting time:
  45. * <ul>
  46. * <li>{@link #sleep Thread.sleep}</li>
  47. * <li>{@link Object#wait(long) Object.wait} with timeout</li>
  48. * <li>{@link #join(long) Thread.join} with timeout</li>
  49. * <li>{@link LockSupport#parkNanos LockSupport.parkNanos}</li>
  50. * <li>{@link LockSupport#parkUntil LockSupport.parkUntil}</li>
  51. * </ul>
  52. */
  53. TIMED_WAITING,
  54. /**
  55. * Thread state for a terminated thread.
  56. * The thread has completed execution.
  57. */
  58. TERMINATED;
  59. }

image.png

  1. 线程创建之后,不会立即进入就绪状态,因为线程的运行需要一些条件(比如内存资源),只有线程运行需要的所有条件满足了,才进入就绪状态。
  2. 当线程进入就绪状态后,不代表立刻就能获取CPU执行时间,也许此时CPU正在执行其他的事情,因此它要等待。当得到CPU执行时间之后,线程便真正进入运行状态。
  3. 线程在运行状态过程中,可能有多个原因导致当前线程不继续运行下去,比如用户主动让线程睡眠(睡眠一定的时间之后再重新执行)、用户主动让线程等待,或者被同步块给阻塞,此时就对应着多个状态:time waiting(睡眠或等待一定的事件)、waiting(等待被唤醒)、blocked(阻塞)。
  4. 当由于突然中断或者子任务执行完毕,线程就会被消亡。