线程五大状态及其常用方法

线程五大状态及其常用方法

线程的五大状态

生老病死乃人之常情,线程也是如此,当一个程序被执行开始,线程就开始了它的生命周期,直至程序运行结束,线程也随之死亡。

线程的五大状态分别为:新建、就绪、运行、阻塞及死亡;

五大状态的关系如下图所示:

新建状态

在生成线程对象之后,调用该对象的start方法之前,此时线程处于新建状态。

就绪状态

当调用了线程对象的start方法之后,该线程就进入了就绪状态,但是此时线程调度程序还没有把该线程设置为当前线程,即CPU还未调度这个线程进行运行,此时的线程就处于就绪状态。并且在线程开始运行之后,从等待或者睡眠中被激活之后,也会处于就绪状态。

运行状态

线程调度程序将处于就绪状态的线程设置为当前线程(线程被CPU调度),此时线程转为运行状态,开始运行重写的run()方法当中的代码。

阻塞状态

通常是为了等待某个事件的发生(比如说某项资源就绪)之后再继续运行(由运行状态转为阻塞状态)。sleep(),suspend(),wait()等方法都可以导致线程阻塞。

死亡状态

如果一个线程的run()方法执行结束或者调用stop()方法后,该线程就会死亡。对于已经死亡的线程,无法再使用start()方法令其进入就绪。

常用方法

sleep()——线程休眠

  • sleep(时间):指定当前进程阻塞的毫秒数;

  • sleep时间到达之后,线程进入就绪状态(等待CPU调度之后再执行);

  • sleep()可以模拟网络延时、倒计时等等;

  • 每一个对象都有一个锁,sleep不会释放锁。

示例

package state;

import java.text.SimpleDateFormat;
import java.util.Date;

public class TestSleep {
   public static void main(String[] args) throws InterruptedException {
//       Time time = new Time();
//       time.time();

       DT dt = new DT();
       dt.date();
  }
}

//实现倒计时
class Time{
   int num=20;
   public void time() throws InterruptedException {
       while(true){
           Thread.sleep(1000);
           System.out.println(num--);

           if(num<0)
               break;
      }

  }
}

//实现日期时间的变化
class DT{
   public void date() throws InterruptedException {
       Date date = new Date(System.currentTimeMillis());   //获取时间
       while(true){
           Thread.sleep(1000);
           System.out.println(new SimpleDateFormat("HH:mm:ss").format(date));
           date=new Date(System.currentTimeMillis());
      }
  }
}

yield()——线程礼让

  • 线程礼让是让当前正在执行的线程暂停,但不阻塞;

  • 将线程从运行状态转为就绪状态,同其他都属于就绪状态的线程一起再次接受CPU的调度;

  • 礼让后让CPU重新调度,但礼让不一定都能礼让成功(即让其他线程先执行),而是由CPU决定。

示例

package state;

//线程礼让 yield();

public class TestYield {
   public static void main(String[] args) {
       MyYield myYield = new MyYield();
       new Thread(myYield,"A ").start();
       new Thread(myYield,"B ").start();
  }
}

//线程类
class MyYield implements Runnable{

   @Override
   public void run() {
       System.out.println(Thread.currentThread().getName()+"is running......");
       Thread.yield();     //线程礼让
       System.out.println(Thread.currentThread().getName()+"is stopped......");
  }
}

join()——线程强制执行

  • join方法可以让目标线程马上立即开始执行,待执行完成后再去执行被暂停的进程,这些被暂停的进程会暂时处于阻塞状态;

  • 简单理解:普通用户排队打饭,来了个VIP用户,直接插队(join()),其他普通用户只能等这个VIP打完饭才能继续打饭。

示例

package state;

//join:线程强制执行

public class TestJoin implements Runnable {


   @Override
   public void run() {
       System.out.println("老大来了,我可是VIP!!!");
  }

   public static void main(String[] args) throws InterruptedException {
       TestJoin testJoin = new TestJoin();
       Thread thread = new Thread(testJoin);
       thread.start();

       for (int i = 0; i < 200; i++) {
           if(i==150)
               thread.join();      //线程强制执行   插队!!!
           System.out.println("Main"+i);
      }

  }
}

观测线程状态方法:getState()

示例:(查看一个线程自新建至死亡的过程)

package state;

public class TestState implements Runnable {
   @Override
   public void run() {
       try {
           Thread.sleep(3000);
           System.out.println("123456789");
      } catch (InterruptedException e) {
           e.printStackTrace();
      }
  }

   public static void main(String[] args) throws InterruptedException {
       TestState testState = new TestState();
       Thread thread = new Thread(testState);

       //观测线程状态:
       Thread.State state = thread.getState();
       System.out.println(state);

       thread.start(); //启动线程
       state = thread.getState();  //获取启动后线程状态
       System.out.println(state);

       //观测线程状态:
       while (state != Thread.State.TERMINATED){
           Thread.sleep(100);
           state = thread.getState();
           System.out.println(state);

      }
  }
}

执行结果中表示线程生命周期的关键字:

  • NEW——尚未启动的进程处于此状态;

  • RUNNABLE——在Java虚拟机中运行的线程处于此状态;

  • BLOCKED——被阻塞等待监视器锁定的线程处于此状态;

  • WAITING——正在等在另一个线程执行特定动作的线程处于此状态;

  • TIMED-WAITING——正在等在另一个线程执行动作达到指定等待时间的线程处于此状态;

  • TERMINATED——已退出的线程处于此状态。

原文地址:https://www.cnblogs.com/awong18/p/13154201.html