i3geek.com
闫庚哲的个人博客

Java 线程生命周期,状态转换和优先级

当线程被创建并启动之后,它既不是一启动就进入执行状态,也不是一直处于执行状态,在其生命周期中,要经过“新建(New)”、“就绪(Runnable)”、“运行(Running’)”、“阻塞(Blocked)”和“死亡(Dead)”五种状态。线程在创建之后,不可能一直霸占着CPU独立运行,需要在多个线程之间切换,所以大部分时间处于运行、阻塞之间切换。

新建和就绪状态

(1)、当用new关键字创建一个线程的时候,该线程就处于新建状态;处于新建状态的线程只是一个空的线程对象,系统不为它分配资源。

(2)、调用start()方法之后,将为线程分配必须的系统资源,线程就进入了就绪状态。当不能立刻进入运行状态,要等待JVM里线程调度器的调度。

注意:只能对处于新建状态的线程调用start()方法,否则会引发异常。这一状态并不是运行中状态(Running),因为线程也许实际上并未真正运行。

运行和阻塞状态

 (1)如果处于就绪状态的线程获得了CPU,就开始执行run方法,处于了运行状态。当分配的时间用完后,又进入了就绪状态,等待下次分配到CPU在进入运行状态。
(2)遇到以下几种情况,线程会进入阻塞状态:
  • 线程调用sleep()方法主动放弃所占用的处理器资源
  • 线程调用了一个阻塞式IO方法,在该方法返回之时,该线程被阻塞
  • 线程试图获得一个同步监视器,但该同步监视器正被其他线程所持有。
  • 现成在等待某个通知(notify)
  • 线程调用了线程的suspend()方法将该线程挂起。该方法容易造成死锁,应尽量避免使用该方法。
(3)进入阻塞状态的程序遇到以下情况才能恢复进入就绪状态,等待分配到资源进入运行状态:
  • 调用sleep()方法的线程经过了指定时间
  • 线程调用的阻塞式IO方法已经返回
  • 线程成功的获得了试图取得的同步监视器
  • 线程正在等待的某个通知时,其他线程发出了一个通知(signal)
  • 处于挂起状态的线程被调用了resume()恢复方法

死亡状态

(1)run()或call()方法执行完成,线程正常结束;
(2)线程抛出一个未捕获的Exception或Error;
(3)直接调用该线程的stop()方法来结束该线程———该方法容易导致死锁,不推荐。

状态间转换

注意

  • 当主线程结束时,其他线程不收任何影响,并不会随之结束。一旦子线程启动起来后,他就拥有和主线程相同的地位,他不会受主线程的影响。
  • 为了测试某个线程是否已经死亡,可以调用线程对象的isAlive方法,当线程处于就绪、运行、阻塞3中状态是,该方法返回true;当线程处于新建、死亡2种状态时,该方法将返回false。
  • 不要试图对一个已经死亡的线程调用start()方法使它重新启动,该线程不可再次作为线程执行。start方法只能对处于新建状态的线程多使用,且只能使用一次!

wait与sleep的区别

  1. wait方法是Object类提供的,而sleep方法是Thread类提供的。
  2. wait方法必须在同步锁中使用,且wait后,线程释放了CPU资源与锁资源。而sleep方法,没有限定必须在同步锁中使用。且sleep后,只会释放CPU资源。而不会释放同步锁资源。

线程的优先级

线程的优先级及设置


线程的优先级是为了在多线程环境中便于系统对线程的调度,优先级高的线程将优先执行。一个线程的优先级设置遵从以下原则

  • 线程创建时,子继承父的优先级。
  • 线程创建后,可通过调用setPriority()方法改变优先级。
  • 线程的优先级是1-10之间的正整数。(1- MIN_PRIORITY;5-NORM_PRIORITY;10-MAX_PRIORITY)默认值是5。

 

但是不能依靠线程的优先级来决定线程的执行顺序。

线程的调度策略


线程调度器选择优先级最高的线程运行。但是,如果发生以下情况,就会终止线程的运行

  • 线程体中调用了y ield()方法,让出了对CPU的占用权。
  • 线程体中调用了s leep()方法,使线程进入睡眠状态。
  • 线程由于I/O操作而受阻塞。
  • 另一个更高优先级的线程出现。
  • 在支持时间片的系统中,该线程的时间片用完。
赞(0)
未经允许不得转载:爱上极客 » Java 线程生命周期,状态转换和优先级
分享到: 更多 (0)

评论 1

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址
  1. #1

    总结的很好

    董不董你懂吗4年前 (2016-03-04)回复