线程的状态
初始状态
实现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的锁被别的线程占有,线程进入同步队列,即同步队列里面放的都是想争夺对象锁的线程。同步队列是在同步的环境下才有的概念,一个对象对应一个同步队列。
线程各个方法的调用与对象的等待队列、同步队列之间的关系如下所示: