线程的状态

初始状态

实现Runnable接口和继承Thread可以得到一个线程类,new一个实例出来,线程就进入了初始状态。

就绪状态

就绪状态意味着线程处于可执行的状态,但是并未真正执行。要等到调度程序选到就绪的线程,线程才会真正占用CPU,执行。

进入就绪状态的几种情况:

  • 调用线程的start()方法
  • 当前线程的sleep()方法结束
  • 当前线程调用其他线程的join()方法,其他线程运行结束时,当前线程进入就绪状态
  • 等待用户输入,输入完毕时
  • 线程拿到了对象锁
  • 线程时间片用完了
  • 线程调用yield()方法

运行中状态

线程调度程序从就绪的线程中选择一个线程进入运行状态。这也是线程进入运行状态的唯一一种方式。

阻塞状态

线程在尝试获得锁但是失败时的状态。

等待

处于等待状态的线程不会被分配CPU执行时间,它们要被显式地唤醒,否则会处于无限期等待的状态。

超时等待

线程处于等待状态,不过在达到一定时间后它们会自动唤醒。

终止状态

  • 当线程的run()方法完成时,或者主线程的main()方法完成时,它就终止了。这个线程对象也许是活的,但是它已经不是一个单独执行的线程。线程一旦终止就不能复生。
  • 对一个终止的线程上调用start()方***抛出java.lang.IllegalThreadStateException异常。

线程的方法

  • Thread.sleep(long millis):当前执行中线程调用此方法,当前线程进入超市等待状态状态,但不释放对象锁,millis后线程自动苏醒进入就绪状态。作用:给其它线程执行机会的最佳方式。
  • Thread.yield():当前执行中线程调用此方法,当前线程放弃获取到的CPU时间片,由运行状态变为就绪状态,但不释放锁。之后调度器再次从就绪线程池选择线程执行,因此刚刚yield()了的线程也可能又被选中。
  • t.join()/t.join(long millis):当前线程里调用其它线程t的join方法,当前线程进入等待/超时等待状态,但当前线程不会释放已经持有的对象锁。线程t执行完毕或者millis时间到,当前线程进入就绪状态。
  • Object.wait():当前线程调用线程的对象锁的对象的wait()方法,释放对象锁,线程进入等待队列。依靠notify()/notifyAll()唤醒或者wait(long timeout)中直至timeout时间到自动唤醒。
  • Object.notify():唤醒在此对象监视器上等待的单个线程,选择是任意性的。notifyAll()唤醒在此对象监视器上等待的所有线程。

线程与对象的等待队列、同步队列

  • 等待队列:线程必须被显式唤醒或直至被设定的时间,才能从等待队列出来。
  • 同步队列:线程想调用对象A的同步方法时,发现对象A的锁被别的线程占有,线程进入同步队列,即同步队列里面放的都是想争夺对象锁的线程。同步队列是在同步的环境下才有的概念,一个对象对应一个同步队列。

线程各个方法的调用与对象的等待队列、同步队列之间的关系如下所示:
图片说明

参考

https://blog.csdn.net/qq_22771739/article/details/82529874