线程生命状态

线程的状态转换:

1、新建状态
用new Thread()建立一个线程对象后,该线程对象就处于新生状态。

2、就绪状态
通过调用线程的start方法进入就绪状态(runnable)。注意:不能对已经启动的线程再次调用start()方法,否则会出现Java.lang.IllegalThreadStateException异常。
处于就绪状态的线程已经具备了运行条件,但还没有分配到CPU,处于线程就绪队列(就绪池),等待系统为其分配CPU。
Note:如果希望子线程调用start()方法后立即执行,可以使用Thread.sleep()方式使主线程睡眠一伙儿,转去执行子线程。

3、运行状态
处于运行状态的线程最为复杂,它可以变为阻塞状态、就绪状态和死亡状态。
处于就绪状态的线程,如果获得了cpu的调度,就会从就绪状态变为运行状态,执行run()方法中的任务。
如果该线程失去了cpu资源,就会又从运行状态变为就绪状态,重新等待系统分配资源。
也可以对在运行状态的线程调用yield()方法,它就会让出cpu资源,再次变为就绪状态。

4、阻塞状态
当发生如下情况时,线程会让出CPU控制权并暂时停止自己的运行,从运行状态变为阻塞状态:
① 线程调用sleep方法主动释放CPU控制权
② 线程调用一个阻塞式IO方法,在该方法返回之前,该线程被阻塞
③ 线程试图获得一个同步监视器,但更改同步监视器正被其他线程所持有
④ 线程在等待某个通知(notify)
⑤ 程序调用了线程的suspend方法将线程挂起。不过该方法容易导致死锁,所以程序应该尽量避免使用该方法。
在阻塞状态的线程不能进入就绪队列。只有当引起阻塞的原因消除时,如睡眠时间已到,或等待的I/O设备空闲下来,线程便转入就绪状态,重新到就绪队列中排队等待,被系统选中后从原来停止的位置开始继续运行。
当发生如下情况时,线程会从运行状态变为阻塞状态:

5、死亡状态
当线程的run()方法执行完,或者被强制性地终止,例如出现异常,或者调用了stop()、desyory()方法等等,就会从运行状态转变为死亡状态。
线程一旦死亡,就不能复生。如果在一个死去的线程上调用start()方法,会抛出java.lang.IllegalThreadStateException异常。

Note:

1. sleep() 是Thread的静态方法,最好不要用Thread的实例对象调用它,因为它睡眠的始终是当前正在运行的线程,而不是调用它的线程对象,它只对正在运行状态的线程对象有效。

2. Java线程调度是Java多线程的核心,只有良好的调度,才能充分发挥系统的性能,提高程序的执行效率。

但是不管程序员怎么编写调度,只能最大限度的影响线程执行的次序,而不能做到精准控制
使用sleep方法之后,线程是进入阻塞状态的,只有当睡眠的时间结束,才会重新进入到就绪状态,而就绪状态进入到运行状态,是由系统控制的,我们不可能精准的去干涉它,所以如果调用Thread.sleep(1000)使得线程睡眠1秒,可能结果会大于1秒。

3. yield()方法

yield()方法和sleep()方法有点相似,也是Thread类提供的一个静态的方法,它也可以让当前正在执行的线程暂停,让出cpu资源给其他的线程。
但是和sleep()方法不同的是,它不会进入到阻塞状态,而是进入到就绪状态。

4. join()方法,线程合并
线程的合并的含义就是将几个并行线程的线程合并为一个单线程执行,应用场景是当一个线程必须等待另一个线程执行完毕才能执行时,Thread类提供了join方法来完成这个功能,注意,它不是静态方法。
从上面的方法的列表可以看到,它有3个重载的方法:
void join()    
    当前线程等待加入该线程后面,等待该线程终止。即,等待该线程执行完毕后再执行当前线程。    
void join(long millis)    
    当前线程等待该线程终止的时间最长为 millis 毫秒。 如果在millis时间内,该线程没有执行完,那么当前线程进入就绪状态,重新等待cpu调度   
void join(long millis,int nanos)    
    等待该线程终止的时间最长为 millis 毫秒 + nanos 纳秒。如果在millis时间内,该线程没有执行完,那么当前线程进入就绪状态,重新等待cpu调度

5. 守护线程

守护线程与普通线程写法上基本么啥区别,调用线程对象的方法setDaemon(true),则可以将其设置为守护线程。

setDaemon方法的详细说明:
public final void setDaemon(boolean on)将该线程标记为守护线程或用户线程。当正在运行的线程都是守护线程时,Java 虚拟机退出。该方法必须在启动线程前调用。

实际上:JRE判断程序是否执行结束的标准是所有的前台执线程行完毕了,而不管后台线程的状态,因此,在使用后台线程(守护线程)时候一定要注意这个问题。

守护线的好处就是你不需要关心它的结束问题。例如你在你的应用程序运行的时候希望播放背景音乐,如果将这个播放背景音乐的线程设定为非守护线程,那么在用户请求退出的时候,

不仅要退出主线程,还要通知播放背景音乐的线程退出;如果设定为守护线程则不需要了。

6. 如何结束一个线程

Thread.stop()、Thread.suspend、Thread.resume、Runtime.runFinalizersOnExit这些终止线程运行的方法已经被废弃了,使用它们是极端不安全的!

想要安全有效的结束一个线程,只要保证在一定的情况下,run方法能够执行完毕即可。而不是while(true)的无线循环。

有些时候线程的run()方法不能正常的执行完毕(可能在运行时转成了阻塞),这种情况下可以借助Thread对象的interrupt()方法将中断状态设置为true来结束一个线程。

当一个线程处于sleep、wait、join这三种状态之一的时候,如果此时他的中断状态为true,那么它就会抛出一个InterruptedException的异常,并将中断状态重新设置为false。

我们看看sleep、wait、join方法的声明:

public final void wait() throws InterruptedException
public static native void sleep(long millis) throws InterruptedException
public final void join() throws InterruptedException  

可以看到,这三者有一个共同点,都抛出了一个InterruptedException的异常。所以,我们可以使用interrupt这个巧妙的方式结束掉这种情况下的线程。

原文地址:https://www.cnblogs.com/lcj12121/p/11370282.html

时间: 2024-10-08 08:57:00

线程生命状态的相关文章

线程的生命周期 - 理解Java中线程的状态

刚刚开始学cocos2-x,仅仅是按照教程把已经安了一般Android的开发环境的eclipse重新升级到安装好cdt和ndk就花了我几十小时,差点都要放弃了. 参考博客 D:\cocos2d-x\cocos2d-x-2.2.3\cocos2dx\platform\third_party\android\prebuilt 说说大概的过程: 下载ndk插件,ndk包,cdt插件.最开始我按照书上的下载了cocos2d-x 2.0.1,希望跟书上统一起来,这样以后学习的时候可以参考书上的也不会遇到太

线程的生命周期和线程的状态转换图

一.线程的生命周期 1.线程的5种状态:新建(New),就绪(Runnable),运行(Running),阻塞(Blocked),死亡(Dead) 2.线程的生命周期图解:(参考传智播客刘意2015Java基础视频讲义) 二.线程的状态转换图 1.线程的5种状态:新建(New),就绪(Runnable),运行(Running),阻塞(Blocked),死亡(Dead) 线程变化的状态转换图例如以下: 1)新建状态(New):新创建了一个线程对象. 2)就绪状态(Runnable):线程对象创建后

Java学习之==>Java线程生命周期与状态切换

一.Java线程生命周期与状态切换 这些状态的描述可以总结成下图: NEW 一个刚创建但尚未启动的Java线程实例就是处于 NEW 状态 public class App { public static void main(String[] args) { Thread thread = new Thread(); Thread.State state = thread.getState(); System.out.println(state); } } // 输出结果 NEW RUNNABLE

线程的状态和生命周期

http://blog.csdn.net/lonelyroamer/article/details/7949969 线程的状态转换: 1.新建状态用new Thread()建立一个线程对象后,该线程对象就处于新生状态. 2.就绪状态通过调用线程的start方法进入就绪状态(runnable).注意:不能对已经启动的线程再次调用start()方法,否则会出现Java.lang.IllegalThreadStateException异常.处于就绪状态的线程已经具备了运行条件,但还没有分配到CPU,处

Java笔记七.线程间通信与线程生命的控制

线程间通信与线程生命的控制 一.线程通信方法 Java是通过Object类的wait.notify.notifyAll这几个方法来实现进程键的通信.由于所有的类都是从Object继承的,因此在任何类中都可以直接使用这些方法. wait:告诉当前线程放弃监视器并进入睡眠状态,知道其他线程进入同一监视器并调用notify为止; notify:唤醒同一对象监视器中调用wait的第一个线程.用于类似饭馆有一个空位后通知所有等候就餐的顾客中的第一位可以入座的情况: notifyAll:唤醒同一对象监视器中

线程生命周期

线程的生命周期:一个线程从创建到消亡的过程 如下图,表示线程生命周期中的各个状态: 线程的生命周期可以分为五个状态: 1.创建状态: 当用new操作符创建一个新的线程对象时,该线程处于创建状态. 处于创建状态的线程只是一个空的线程对象,系统不为它分配资源. 2.可运行状态[runnable]: 执行线程的start()方法将为线程分配必须的系统资源,安排其运行,并调用线程体——run()方法, 这样就使得该线程处于可运行状态(Runnable). 这一状态并不是运行中状态(Running),因为

线程的状态和常用方法

线程的状态一个线程从创建,启动到终止的整个过程称为线程的生命周期,在其间的任何时刻,线程总是处于某个特定状态.这些状态如下:新建状态:线程对象已经创建,对应new语句.就绪状态:就绪状态也可叫做可执行状态,对应start()方法.运行状态:当处于就绪的线程被调度并获得了cpu等执行必须的资源时,便进入到该状态,即运行了run()方法.等待/阻碍/睡眠状态:三个状态组合为一种,其共同点是线程仍然是活的,但是当前没有条件运行.换句话说,它是可运行的,如果某个事件出现,它可能返回到可运行状态,对应以下

多线程(四)线程生命周期和线程池

一.线程生命周期 线程的5种状态: 新建(New) ,就绪(Runnable),运行(Running),阻塞(Blocked),死亡(Dead)     线程生命周期图: 二.线程池 1.为什么要使用线程池: (1).提高性能 系统启动一个新线程的成本是比较高的,而使用线程池避免了频繁的创建和销毁线程,可以很好地提高性能. 线程池在系统启动时即创建大量空闲的线程,程序将一个Runnable对象或Callable对象传给线程池,线程池就会自动 启动一个线程来执行它们的run()或call()方法,

java基础知识回顾之java Thread类学习(十)--线程的状态以及转化使用的方法介绍

   线程的概述:         线程是程序的多个执行路径,执行调度的单位,依托于进程存在.线程不仅可以共享进程的内存,而且还拥有一个属于自己的内存空间,这段内存空间叫做线程栈,是建立线程的时候由系统分配的,主要用来保存线程内部的数据,如线程执行函数中定义的变量.   java中多线程是一种抢占机制而不是分时机制.抢占机制是指CPU资源师被多个线程所共享,多个线程处于可运行状态,但是只允许一个线程在运行,他们通过竞争的方式抢占CPU.可以参考java 进程与线程的区别  线程的状态: 新生状态