一、JDK帮助手册
打开JDK帮助手册,搜索Thread.State
线程状态容易跟操作系统的进程状态混淆。通过帮助手册,我们可以知道线程的确切状态是6种。
二、线程状态
1. 初始状态
新创建了一个线程对象,但还没有调用start()方法时。
2.1. 就绪状态
- 调用线程的start()方法,此线程进入就绪状态。
- 当前线程sleep()方法结束,当前线程进入就绪状态。
- 其他线程join()结束,当前线程进入就绪状态。
- 当前线程时间片用完了,调用当前线程的yield()方法,当前线程进入就绪状态。
- 锁池里的线程拿到对象锁后,进入就绪状态。
2.2. 运行中状态
线程调度程序从可运行池中选择一个线程获得CPU时间片后,被选中线程进入的状态。这也是线程进入运行状态的唯一一种方式。
3. 阻塞状态
阻塞状态是线程阻塞在进入synchronized关键字修饰的方法或代码块(获取锁)时的状态。
4. 等待状态
处于这种状态的线程不会被分配CPU执行时间,它们要等待被显式地唤醒,否则会处于无限期等待的状态。
5. 超时等待状态
处于这种状态的线程不会被分配CPU执行时间,不过无须无限期等待被其他线程显示地唤醒,在达到一定时间后它们会自动唤醒。
6. 终止状态
- 当线程的run()方法完成时,或者主线程的main()方法完成时,我们就认为它终止了。
- 线程一旦终止了,就不能复生。在一个终止的线程上调用start()方法,会抛出java.lang.IllegalThreadStateException异常。
三、线程方法
1.线程核心方法
-
sleep():Thread.sleep(long millis),一定是当前线程调用此方法,当前线程进入TIME_WAITING状态,但不释放对象锁,millis后线程自动苏醒进入就绪状态。作用:sleep可以模拟网络延时,倒计时等。
-
yield():Thread.yield(),一定是当前线程调用此方法,当前线程放弃获取的cpu时间片,由运行状态变会就绪状态,让OS再次选择线程。作用:让CPU重新调度。实际中yield()无法保证达到让步目的,因为让步的线程还有可能被线程调度程序再次选中。Thread.yield()不会导致阻塞。
-
join():t.join() / t.join(long millis),可以理解为当前线程给其他线程t插队。过程:当前线程里调用其它线程t的join方法,当前线程进入TIME_WAITING/TIME_WAITING状态,当前线程不释放已经持有的对象锁。线程t执行完毕或者millis时间到,当前线程进入就绪状态。
2.wait/notify/notifyAll方法介绍
wait()和notify()是一个系列的方法,都是属于对象Object的方法,不是属于线程的。它们用在线程同步方法或同步块中。
-
wait():obj.wait(),当前线程调用对象的wait()方法,当前线程释放对象锁,进入等待队列。依靠notify()/notifyAll()唤醒或者wait(long timeout)timeout时间到自动唤醒。
-
notify():obj.notify()唤醒在此对象监视器上等待的单个线程,选择是任意性的。
-
notifyAll():obj.notifyAll()唤醒在此对象监视器上等待的所有线程。