java的线程的生命周期五种状态解释

线程的生命周期

1.线程的状态:

在《疯狂java》中介绍了线程有五种状态:新建(new),就绪(Runnable),运行(Running),阻塞(Blocked)和死亡(Dead)

但是我查看thread源码之后,发现线程的状态有六种:

public enum State {
      NEW,
    RUNNABLE,
    BLOCKED,
    WAITING,
    TIMED_WAITING,
    TERMINATED;
}

ps:注释太长了我没有下拉下来,各位感兴趣可以去看看

2.新建和就绪状态

​ 当程序中new了一个thread对象的时候,这个线程处于就绪状态,和其他的对象相同,由jvm分配内存,并且初始化成员变量的数值,这个时候这个线程没有表现出来任何线程的动态特性,也没有执行线程体

​ 当使用了start()方法之后,线程状态转变为就绪状态,但是还没有运行,等待cpu的分配,这个时候是否运行取决于jvm中线程调度器的调度

对于一个thread对象,如果直接使用run()方法,并不算启动了线程,这个时候运行其实是把run()当做普通的方法去执行

下面的这个例子中,currentThread().getName()返回的是main线程的名字

public static class CurThread extends Thread
	{
		public int i=0;
		public void run() {
			for(int j=0;j<10;j++)
				System.out.println("I: "+i+++Thread.currentThread().getName());
		}
	}
	public static void main(String[]__)
	{
		CurThread t=new CurThread();
		t.run();
		//System.out.println(t.isAlive());
		
	}

也就是说实际上,这个时候并不是thread-0去执行。

#小疑问

书上说对于一个线程调用run()会改变这个线程的状态,由于start()方法调用的时候,必须要求线程处于new状态,因此对于一个线程调用run(),在调用start()就会抛出IllegalThreadStateException异常。

但是我在我本地环境尝试的时候,照跑不误。

3.运行和阻塞状态

对于计算机只有一个CPU,那么在任何时候就只有一个线程处于运行状态,在有多个处理器的机器上,会有多个线程并行,当线程数大于处理器数的时候,依然会存在线程在同一个CPU上轮换的情况

抢占式系统调度

当程序使用一段时间之后,系统会剥夺该线程所占用的资源,让其他线程获得执行的机会,在在选择下一个线程的时候,系统会考虑线程的优先级。

对于线程的优先级

  • MAX_PRIORAITY🔟
  • MIN_PRIORITYY1️⃣
  • NORM_PRIORITY5️⃣

协作式调度

只有当一个线程调用了他的sleep(),或者yield()方法后才会主动的放弃所占用的资源

线程之间阻塞和去除阻塞方法的对应关系:

  • sleep():主动放弃所占用的处理器资源

    调用sleep()的线程已经过了指定的时间

  • 线程调用了一个阻塞式的IO方法

    线程调用的阻塞式IO方法已经返回

  • 线程视图获得一个同步监视器

    线程成功获得了视图取得的同步监视器

  • 线程等待某个通知notify

    得到了其他线程的通知

  • 线程调用了线程的suspend()方法将该线程挂起,但是可能会造成死锁,所以应该尽量避免使用该方法

    使用resume()方法回复

图示:

图中可以看出,线程总阻塞状态可以回到就绪,但是就绪状态和运行状态之间转换是收到处理器的调度,但是有一个方法yield()是可以做到控制的。yield()方法通知当前线程取消对资源的占用,但是当前线程在yield之后还是有可能拿到资源,并且重新到达运行状态

4.死亡状态

  • run()方法或者call()方法执行完毕,线程正常结束
  • 线程抛出一个未捕获的Exception方法
  • 直接调用这个线程的stop()方法来结束该线程,不过会有可能造成死锁

ps:注意,当一个线程已经变为死亡状态,调用start()方法就会抛出异常,也就是说对于同一个线程不能同时调用两次start()方法

posted @ 2021-11-05 16:42  写不完作业还要玩  阅读(401)  评论(0编辑  收藏  举报