线程状态

# 线程状态 #   在线程的生命周期中,线程会经历以下状态5种状态:
  • 新建
  • 就绪
  • 运行
  • 阻塞
  • 死亡

  使用new关键字创建线程之后该线程就处于**新建状态**,该对象与其他非线程对象一样,由虚拟机分配内存,初始化成员变量。

  当调用线程对象的start()方法之后,线程就进入到了**就绪状态**,虚拟机会为其创建方法调用栈和程序计数器这个状态的线程才是可以运行的线程,但是并没有开始运行;只有当其获取到CPU后才会执行run()方法,进入到**运行状态**;所以在多次运行结果中我们有时会看到,主线程执行完之后,子线程的run()执行体才开始执行.

public class ThreadStatusTest extends Thread {

    private int i=0;
    public void run() {
        for( ;i<5;i++) {
        System.out.print(this.getName()+"线程中的run方法执行"+" ");
        System.out.println("i的值为:"+i);
    }
    }

    public static void main(String[] args) {
        for(int i=0;i<10;i++) {
            System.out.print("当前线程名字为:"+" ");
            System.out.println(Thread.currentThread().getName()+" " +"循环变量i的值为:"+i);
            if (i==5) {
                /**
                 * 使用new关键字创建线程之后该线程就处于新建状态,该对象与其他非线程* 对象一样,
                 * 由虚拟机分配内存,初始化成员变量
                 */
                ThreadStatusTest t=new ThreadStatusTest();
                /**
                 * 当调用线程对象的start()方法之后,线程就进入到了就绪状态,虚拟机会为其创建方法调用栈和程序计数器
                 * 这个状态的线程才是可以运行的线程,但是并没有开始运行;
                 * 只有当其获取到CPU后才会执行run()方法,进入到运行状态;
                 * 所以在多次运行结果中我们有时会看到,主线程执行完之后,
                 * 子线程的run()执行体才开始执行
                 */
                t.start();
            }
        }
    }

}

  某次运行的输出结果如下所示,可以看到,当主线程中的循环变量为5时,已经启动子线程,但是并没有立即执行子线程的run()方法执行体,在主线程执行完之后,才执行了该方法体,所以线程使用start()方法启动后,不是直接进入到执行状态的。

- 当前线程名字为: main 循环变量i的值为:0
- 当前线程名字为: main 循环变量i的值为:1
- 当前线程名字为: main 循环变量i的值为:2
- 当前线程名字为: main 循环变量i的值为:3
- 当前线程名字为: main 循环变量i的值为:4
- 当前线程名字为: main 循环变量i的值为:5
- 当前线程名字为: main 循环变量i的值为:6
- 当前线程名字为: main 循环变量i的值为:7
- 当前线程名字为: main 循环变量i的值为:8
- 当前线程名字为: main 循环变量i的值为:9
- Thread-0线程中的run方法执行 i的值为:0
- Thread-0线程中的run方法执行 i的值为:1
- Thread-0线程中的run方法执行 i的值为:2
- Thread-0线程中的run方法执行 i的值为:3
- Thread-0线程中的run方法执行 i的值为:4

  一个线程开始运行之后,它也不可能一直处于运行状态,在其运行过程中会被中断,使其他线程获得执行机会,这种线程的调配细节是由底层平台(操作平台)所使用的策略决定的。
  如下为程序某次的运行结果,红色字体部分本是子线程中相邻的执行语句,但是由输出结果可以看到,其被分开执行,因此除非线程的执行体足够短,瞬间被执行结束,否则线程在执行的过程中是一定会被中断来让其它线程获得执行机会。

- 当前线程名字为: main 循环变量i的值为:0
- 当前线程名字为: main 循环变量i的值为:1
- 当前线程名字为: main 循环变量i的值为:2
- 当前线程名字为: main 循环变量i的值为:3
- 当前线程名字为: main 循环变量i的值为:4
- 当前线程名字为: main 循环变量i的值为:5
- 当前线程名字为: main 循环变量i的值为:6
- 当前线程名字为: main 循环变量i的值为:7
- 当前线程名字为:<font color=red>Thread-0线程中的run方法执行</font>  main 循环变量i的值为:8
- 当前线程名字为:<font color=red>i的值为:0</font> 
- main 循环变量i的值为:9
- Thread-0线程中的run方法执行 i的值为:1
- Thread-0线程中的run方法执行 i的值为:2
- Thread-0线程中的run方法执行 i的值为:3
- Thread-0线程中的run方法执行 i的值为:4

  对于抢占式策略的系统而言,系统会给每个可执行的线程一个小时间段来处理任务,该段时间被用完之后,系统就会剥夺该线程所占用的CPU资源,让其它线程获得执行机会,在选择下一个线程时,系统会考虑线程的优先级,所有现代的桌面和服务器系统都采用这种策略。

  当一个线程的运行被系统强行中断之后,就进入到了阻塞状态,被阻塞的线程重新进入到就绪状态,等待线程调度器再次调度它,而不是被阻塞之后,在一定的时机进入直接进人到运行状态。
以下情况也会使得线程进入到阻塞状态:

  • 线程调用sleep()方法或者是yield()方法主动放弃所占用的处理器资源;
  • 线程调用了一个阻塞式的IO方法,在该方法返回之前,该线程被阻塞;
  • 线程试图获取一个被其它线程持有的同步监视器;
  • 线程在等待某个通知;
  • 程序调用了线程的suspend()方法将线程挂起;

  相对应的发生以下情况时可以使被阻塞的线程重新进入到就绪状态,等待被线程调度器调度:

  • 调用sleep()方法的线程经过了指定的时间;
  • 线程调用的阻塞式IO方法已经返回;
  • 线程成功获得了试图获得的同步监视器;
  • 线程接收到等待的通知;
  • 处于挂起状态的线程被调用了resume()恢复方法;


  线程的最后一种状态是线程死亡,线程会以如下三种方式结束:

  • run()或者call()方法执行完成线程正常结束;
  • 线程抛出一个未捕获的异常;
  • 直接调用线程的stop()方法结束线程;


  线程结束之后就处于死亡状态,可以调用线程的isAlive()方法测试线程是否死亡,当线程处于就绪,运行,阻塞状态时,该方法返回true;若线程处于新建或是死亡时,该方法返回false;
注意,子线程一旦启动就拥有和主线程同样的地位,不会受到主线程状态的影响,主线程结束后,子线程并不会随之结束。

public class ThreadStatusTest extends Thread {
    private int i=0;
    public void run() {
        for( ;i<5;i++) {
            //制造异常
            int j=i/0;
            System.out.println(j);
            System.out.print(this.getName()+"线程中的run方法执行"+" ");
            System.out.println("i的值为:"+i);
        }
    }

    public static void main(String[] args) {
        ThreadStatusTest t=new ThreadStatusTest();
        for(int i=0;i<60;i++) {
            System.out.print("当前线程名字为:"+" ");
            System.out.println(Thread.currentThread().getName()+" " +"循环变量i的值为:"+i);
            if (i==30) {
                t.start();
            }
            //保证线程已经启动或,会抛出异常,这时线程一定死亡
            if(!t.isAlive()) {
                System.out.println("子线程死亡"+"i的值为"+i);
            }
        }
    }
}

  以上程序中,在run()方法中制造了除0的异常,其输出结果为如下所示,在循环变量小于30时,线程都处于新建状态,调用isAlive()方法返回的都是false;而在循环变量大于30后,子线程调用start()方法进入到就绪状态,等待调度器调度,这个过程调用isAlive()方法返回的是true,不会输出“子线程死亡……”;一旦子线程开始运行,抛出未捕获的异常,则子线程死亡,调用isAlive()方法返回false,再次循环输出“子线程死亡…….”;

当前线程名字为: main 循环变量i的值为:0
子线程死亡i的值为0
当前线程名字为: main 循环变量i的值为:1
子线程死亡i的值为1
当前线程名字为: main 循环变量i的值为:2
子线程死亡i的值为2
当前线程名字为: main 循环变量i的值为:3
子线程死亡i的值为3
当前线程名字为: main 循环变量i的值为:4
子线程死亡i的值为4
当前线程名字为: main 循环变量i的值为:5
子线程死亡i的值为5
当前线程名字为: main 循环变量i的值为:6
子线程死亡i的值为6
当前线程名字为: main 循环变量i的值为:7
子线程死亡i的值为7
当前线程名字为: main 循环变量i的值为:8
子线程死亡i的值为8
当前线程名字为: main 循环变量i的值为:9
子线程死亡i的值为9
当前线程名字为: main 循环变量i的值为:10
子线程死亡i的值为10
当前线程名字为: main 循环变量i的值为:11
子线程死亡i的值为11
当前线程名字为: main 循环变量i的值为:12
子线程死亡i的值为12
当前线程名字为: main 循环变量i的值为:13
子线程死亡i的值为13
当前线程名字为: main 循环变量i的值为:14
子线程死亡i的值为14
当前线程名字为: main 循环变量i的值为:15
子线程死亡i的值为15
当前线程名字为: main 循环变量i的值为:16
子线程死亡i的值为16
当前线程名字为: main 循环变量i的值为:17
子线程死亡i的值为17
当前线程名字为: main 循环变量i的值为:18
子线程死亡i的值为18
当前线程名字为: main 循环变量i的值为:19
子线程死亡i的值为19
当前线程名字为: main 循环变量i的值为:20
子线程死亡i的值为20
当前线程名字为: main 循环变量i的值为:21
子线程死亡i的值为21
当前线程名字为: main 循环变量i的值为:22
子线程死亡i的值为22
当前线程名字为: main 循环变量i的值为:23
子线程死亡i的值为23
当前线程名字为: main 循环变量i的值为:24
子线程死亡i的值为24
当前线程名字为: main 循环变量i的值为:25
子线程死亡i的值为25
当前线程名字为: main 循环变量i的值为:26
子线程死亡i的值为26
当前线程名字为: main 循环变量i的值为:27
子线程死亡i的值为27
当前线程名字为: main 循环变量i的值为:28
子线程死亡i的值为28
当前线程名字为: main 循环变量i的值为:29
子线程死亡i的值为29

当前线程名字为: main 循环变量i的值为:30
当前线程名字为: main 循环变量i的值为:31
当前线程名字为: main 循环变量i的值为:32
当前线程名字为: main 循环变量i的值为:33
当前线程名字为: main 循环变量i的值为:34
当前线程名字为: main 循环变量i的值为:35
当前线程名字为: main 循环变量i的值为:36
当前线程名字为: main 循环变量i的值为:37
当前线程名字为: main 循环变量i的值为:38
当前线程名字为: main 循环变量i的值为:39
当前线程名字为: main 循环变量i的值为:40
当前线程名字为: main 循环变量i的值为:41
当前线程名字为: main 循环变量i的值为:42
当前线程名字为: main 循环变量i的值为:43
当前线程名字为: main 循环变量i的值为:44
当前线程名字为: main 循环变量i的值为:45
当前线程名字为: main 循环变量i的值为:46
当前线程名字为: main 循环变量i的值为:47
当前线程名字为: main 循环变量i的值为:48
当前线程名字为: main 循环变量i的值为:49
Exception in thread “Thread-0” java.lang.ArithmeticException: / by zero
at thread.learning.status.ThreadStatusTest.run(ThreadStatusTest.java:9)

子线程死亡i的值为49
当前线程名字为: main 循环变量i的值为:50
子线程死亡i的值为50
当前线程名字为: main 循环变量i的值为:51
子线程死亡i的值为51
当前线程名字为: main 循环变量i的值为:52
子线程死亡i的值为52
当前线程名字为: main 循环变量i的值为:53
子线程死亡i的值为53
当前线程名字为: main 循环变量i的值为:54
子线程死亡i的值为54
当前线程名字为: main 循环变量i的值为:55
子线程死亡i的值为55
当前线程名字为: main 循环变量i的值为:56
子线程死亡i的值为56
当前线程名字为: main 循环变量i的值为:57
子线程死亡i的值为57
当前线程名字为: main 循环变量i的值为:58
子线程死亡i的值为58
当前线程名字为: main 循环变量i的值为:59
子线程死亡i的值为59



一旦进行了异常处理,子线程会正常结束,进入死亡状态,此时isAlive()方法同样返回false,输出“子线程死亡i的值为…….”

 public class ThreadStatusTest extends Thread {
    private int i=0;
    public void run() {
        for( ;i<5;i++) {
            //制造异常
            try {//捕获异常之后,子线程会正常结束,进入死亡状态;
                int j=i/0;
                System.out.println(j);
            } catch (Exception e) {
                System.out.println("捕获异常");
            }

            System.out.print(this.getName()+"线程中的run方法执行"+" ");
            System.out.println("i的值为:"+i);
        }
    }

    public static void main(String[] args) {
        ThreadStatusTest t=new ThreadStatusTest();
        for(int i=0;i<60;i++) {
            System.out.print("当前线程名字为:"+" ");
            System.out.println(Thread.currentThread().getName()+" " +"循环变量i的值为:"+i);
            if (i==30) {
                t.start();
            }
            //保证线程已经启动或,会抛出异常,这时线程一定死亡
            if(!t.isAlive()) {
                System.out.println("子线程死亡"+"i的值为"+i);
            }
        }
    }

}

程序输出结果为如下所示,子线程在异常处理后会正常结束。

当前线程名字为: main 循环变量i的值为:0
子线程死亡i的值为0
当前线程名字为: main 循环变量i的值为:1
子线程死亡i的值为1
当前线程名字为: main 循环变量i的值为:2
子线程死亡i的值为2
当前线程名字为: main 循环变量i的值为:3
子线程死亡i的值为3
当前线程名字为: main 循环变量i的值为:4
子线程死亡i的值为4
当前线程名字为: main 循环变量i的值为:5
子线程死亡i的值为5
当前线程名字为: main 循环变量i的值为:6
子线程死亡i的值为6
当前线程名字为: main 循环变量i的值为:7
子线程死亡i的值为7
当前线程名字为: main 循环变量i的值为:8
子线程死亡i的值为8
当前线程名字为: main 循环变量i的值为:9
子线程死亡i的值为9
当前线程名字为: main 循环变量i的值为:10
子线程死亡i的值为10
当前线程名字为: main 循环变量i的值为:11
子线程死亡i的值为11
当前线程名字为: main 循环变量i的值为:12
子线程死亡i的值为12
当前线程名字为: main 循环变量i的值为:13
子线程死亡i的值为13
当前线程名字为: main 循环变量i的值为:14
子线程死亡i的值为14
当前线程名字为: main 循环变量i的值为:15
子线程死亡i的值为15
当前线程名字为: main 循环变量i的值为:16
子线程死亡i的值为16
当前线程名字为: main 循环变量i的值为:17
子线程死亡i的值为17
当前线程名字为: main 循环变量i的值为:18
子线程死亡i的值为18
当前线程名字为: main 循环变量i的值为:19
子线程死亡i的值为19
当前线程名字为: main 循环变量i的值为:20
子线程死亡i的值为20
当前线程名字为: main 循环变量i的值为:21
子线程死亡i的值为21
当前线程名字为: main 循环变量i的值为:22
子线程死亡i的值为22
当前线程名字为: main 循环变量i的值为:23
子线程死亡i的值为23
当前线程名字为: main 循环变量i的值为:24
子线程死亡i的值为24
当前线程名字为: main 循环变量i的值为:25
子线程死亡i的值为25
当前线程名字为: main 循环变量i的值为:26
子线程死亡i的值为26
当前线程名字为: main 循环变量i的值为:27
子线程死亡i的值为27
当前线程名字为: main 循环变量i的值为:28
子线程死亡i的值为28
当前线程名字为: main 循环变量i的值为:29
子线程死亡i的值为29
当前线程名字为: main 循环变量i的值为:30
当前线程名字为: main 循环变量i的值为:31
当前线程名字为: main 循环变量i的值为:32
当前线程名字为: main 循环变量i的值为:33
当前线程名字为: 捕获异常
Thread-0线程中的run方法执行 i的值为:0
捕获异常
Thread-0线程中的run方法执行 i的值为:1
捕获异常
Thread-0线程中的run方法执行 i的值为:2
捕获异常
Thread-0线程中的run方法执行 i的值为:3
捕获异常
Thread-0线程中的run方法执行 i的值为:4
main 循环变量i的值为:34
子线程死亡i的值为34
当前线程名字为: main 循环变量i的值为:35
子线程死亡i的值为35
当前线程名字为: main 循环变量i的值为:36
子线程死亡i的值为36
当前线程名字为: main 循环变量i的值为:37
子线程死亡i的值为37
当前线程名字为: main 循环变量i的值为:38
子线程死亡i的值为38
当前线程名字为: main 循环变量i的值为:39
子线程死亡i的值为39
当前线程名字为: main 循环变量i的值为:40
子线程死亡i的值为40
当前线程名字为: main 循环变量i的值为:41
子线程死亡i的值为41
当前线程名字为: main 循环变量i的值为:42
子线程死亡i的值为42
当前线程名字为: main 循环变量i的值为:43
子线程死亡i的值为43
当前线程名字为: main 循环变量i的值为:44
子线程死亡i的值为44
当前线程名字为: main 循环变量i的值为:45
子线程死亡i的值为45
当前线程名字为: main 循环变量i的值为:46
子线程死亡i的值为46
当前线程名字为: main 循环变量i的值为:47
子线程死亡i的值为47
当前线程名字为: main 循环变量i的值为:48
子线程死亡i的值为48
当前线程名字为: main 循环变量i的值为:49
子线程死亡i的值为49
当前线程名字为: main 循环变量i的值为:50
子线程死亡i的值为50
当前线程名字为: main 循环变量i的值为:51
子线程死亡i的值为51
当前线程名字为: main 循环变量i的值为:52
子线程死亡i的值为52
当前线程名字为: main 循环变量i的值为:53
子线程死亡i的值为53
当前线程名字为: main 循环变量i的值为:54
子线程死亡i的值为54
当前线程名字为: main 循环变量i的值为:55
子线程死亡i的值为55
当前线程名字为: main 循环变量i的值为:56
子线程死亡i的值为56
当前线程名字为: main 循环变量i的值为:57
子线程死亡i的值为57
当前线程名字为: main 循环变量i的值为:58
子线程死亡i的值为58
当前线程名字为: main 循环变量i的值为:59
子线程死亡i的值为59

猜你喜欢

转载自blog.csdn.net/sandyxin5208/article/details/80255828