线程执行过程中的状态

1 线程执行过程中的状态

  1. new 初始化状态
  2. runnalbe 可运行/运行状态
  3. blocked 阻塞状态
  4. waiting 等待状态,无时间限制
  5. timed_waiting 超时等待,有时间限制
  6. terminated 终止状态

1.1 各个状态介绍

1.1.1 new 初始化状态

实现Runnable接口和继承Thread可以得到一个线程类,从而可以new一个实例出来,线程进入初始化。

    public class ThreadTest extends Thread{
        private String name;

        public ThreadTest(String name){this.name = name}

        public void run(){
            for(int i = 1; i < 11; i++){
                System.out.println(Thread.currentThread().getName() + " Thread " + i);
            }
        }

        public static void main(String[] args){
            ThreadTest t1 = new ThreadTest("thread1");
            ThreadTest t2 = new ThreadTest("thread2");
            ThreadTest t3 = new ThreadTest("thread3");
            t1.start();
            t2.start();
            t3.start();
        }
    }
    public class TestRunnable implements Runnable{
        public void run(){
            for(int i = 1; i < 11; i++){
                System.out.println(Thread.currentThread().getName() + " Thread " + i);
            }
        }

        public static void main(String[] args){
            ThreadTest t1 = new ThreadTest("thread1");
            ThreadTest t2 = new ThreadTest("thread2");
            ThreadTest t3 = new ThreadTest("thread3");
            t1.start();
            t2.start();
            t3.start();
        }
    }

1.1.2 Runnable 就绪,运行中的状态

  1. 就绪状态只是说你自己在运行,调度程序没有选到你,你就永远是就绪状态。
  2. 调用线程的start()方法,线程进入就绪状态
  3. 当前线程slee()方法结束,其他进程join()结束,等待用户输入完毕,某个线程拿到对象锁,这些线程也将进入就绪状态。
  4. 当前线程时间片用完了,调用当前线程的yield()方法,当前线程进入就绪状态。
  5. 锁池里的线程拿到对象锁后,进入就绪状态。

1.1.3 Running 运行中状态

线程调度程序可以从运行池中选择一个线程作为当前线程时,线程进入运行状态。

这也是线程进入运行状态的唯一方式。

1.1.4 Blocked 阻塞状态

阻塞状态是指线程阻塞在进入synchronized关键字修饰的方法或代码块(获取锁)之前的状态。

1.1.5 Waiting 等待状态

调用sleep()或者wait()方法后,线程处于waiting状态,等待被唤醒。

1.1.6 timed_waiting 等待超时状态

调用sleep()或者wait()方法后,线程处于timed_waiting状态,等待被唤醒,或者超时被自动唤醒。

1.1.7 treminated 终止状态

  1. 当前线程的run方法完成时,或者主线程的main方法完成时,我们就认为他终止了。这个对象也许是活的,但是他已经不是一个独立执行的线程。线程一旦停止,就不能复生。
  2. 在一个终止线程上调用start方法,会抛出java.long.IllegalThreadStateException异常

1.2 线程之间状态的切换

1.2.1 new -> runnable

  • 实现runnable接口,或者集成thread类,可以获得一个线程类,创建这个类的实例对象,就是new
  • new状态的线程不会被操作系统调度,也不会被执行
  • 调用的这个线程的start方法,将new状态转换成runnable状态

1.2.2 runnable -> block -> runnable

  • runnable线程获得cpu运行时间,执行run方法,进入running状态
  • running线程进入synchronized同步块,可能进行同步阻塞或IO阻塞,进入blocked状态
  • block线程同步synchronized同步块,可能进行同步块释放或IO完成,进入runnable状态

只有当线程等待synchronized的隐形锁时,线程才会从runnable向blocked状态转换。

被synchronizded关键字修饰的方法、代码,在同一时刻,只允许一个线程运行。

所以在这种情况下,等待的线程就会从runnable变为block,当等待的线程获得synchronized隐式锁时,就会从block状态转到如runnable。

1.2.3 runnable -> running -> waiting -> runnable

  • 有三种情况会触发线程从runnable转到waiting
    • 获得synchronized的线程调用Object.wait()
    • 调用线程同步Thread.join方法
      • 线程A在runnable。得到cpu执行时间后,变为running
      • 线程B调用join方法,插队。
      • 线程A进入主动等待状态,变为waiting
      • 线程B执行完毕了以后,线程A变为runnable
    • 调用LockSupport.park方法。Java并发包中的锁,都是基于LockSupport对象实现的。
      • 调用LockSupport.park(),线程会阻塞,从running变为waiting
      • 调用LockSupport.unpark(),线程被唤醒,从waiting变为runnable

1.2.4 runnable -> timed_waiting

  • 有五种情况会出发线程从runnable转到timed_waiting
    • 调用带超时参数的Thread.sleep(long millis)
    • 获得synchronized线程,调用带参数的OBject.wait(long deadline)方法
    • 调用带参数的LockSupport.parkNanos(Object blocker, long deadline)
    • 调用带超时参数的LocalSupport.parkUntil(long deadline)

1.2.5 runnable -> terminated

这是一个自动的过程,一个线程正常运行完毕以后,就会变成terminated

如果运行时,有异常抛出,也会终止进程

或者调用interrupt方法,中断线程。

posted @ 2021-06-10 15:56  Yiyang_Cai  阅读(255)  评论(0编辑  收藏  举报