一、生命周期的五种状态

1、新建(new Thread)
当创建Thread类的一个实例(对象)时,此线程进入新建状态(未被启动)。
例如:Thread  t1=new Thread();

2、就绪(runnable)
线程已经被启动,正在等待被分配给CPU时间片,也就是说此时线程正在就绪队列中排队等候得到CPU资源。例如:t1.start();

3、运行(running)

线程获得CPU资源正在执行任务(run()方法),此时除非此线程自动放弃CPU资源或者有优先级更高的线程进入,线程将一直运行到结束。

处于运行状态的线程最为复杂,它可以变为阻塞状态、就绪状态和死亡状态。

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

当发生如下情况是,线程会从运行状态变为阻塞状态:

①、线程调用sleep方法主动放弃所占用的系统资源

②、线程调用一个阻塞式IO方法,在该方法返回之前,该线程被阻塞

③、线程试图获得一个同步监视器,但更改同步监视器正被其他线程所持有

④、线程在等待某个通知(notify)

⑤、程序调用了线程的suspend方法将线程挂起。不过该方法容易导致死锁,所以程序应该尽量避免使用该方法。

当线程的run()方法执行完,或者被强制性地终止,例如出现异常,或者调用了stop()、desyory()方法等等,就会从运行状态转变为死亡状态。

当线程被阻塞后,其他线程将有机会执行。被阻塞的线程会在合适的时候重新进入就绪状态,注意是就绪状态不是运行状态。

也就是被阻塞线程在阻塞解除后,必须重新等待线程调度器再次调用它。

针对上面线程阻塞的情况,发生以下特定的情况可以解除阻塞,让进程进入就绪状态:

A、调用sleep方法的经过了指定的休眠时间

B、线程调用的阻塞IO已经返回,阻塞方法执行完毕

C、线程成功获得了试图同步的监视器

D、线程正在等待某个通知,其他线程发出了通知

E、处于挂起状态的线程调用了resume恢复方法

线程从阻塞状态只能进入就绪状态,无法进入运行状态。而就绪和运行状态之间的转换通常不受程序控制,而是由系统调度所致的。

当就绪状态的线程获得资源时,该线程进入运行状态;当运行状态的线程事情处理器资源时就进入了就绪状态。

但对调用了yield的方法就例外,此方法可以让运行状态转入就绪状态。

4、死亡(dead)
当线程执行完毕或被其它线程杀死,线程就进入死亡状态,这时线程不可能再进入就绪状态等待执行。

Thread.stop()、Thread.suspend、Thread.resume、Runtime.runFinalizersOnExit这些终止线程运行的方法已经被废弃了,使用它们是极端不安全的!想要安全有效的结束一个线程,可以使用下面的方法。

1、正常执行完run方法,然后结束掉

2、控制循环条件和判断条件的标识符来结束掉线程

比如说run方法这样写:

    class MyThread extends Thread {  int i=0;  @Override  public void run() {  while (true) {  if(i==10)  return;  i++;  System.out.println(i);  }  }  }  

只要保证在一定的情况下,run方法能够执行完毕即可。而不是while(true)的无线循环。

3、使用interrupt结束一个线程。

诚然,使用第2中方法的标识符来结束一个线程,是一个不错的方法,但是如果,该线程是处于sleep、wait、join的状态的时候,while循环就不会执行,那么我们的标识符就无用武之地了,当然也不能再通过它来结束处于这3种状态的线程了。

可以使用interrupt这个巧妙的方式结束掉这个线程。

我们看看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的异常。

在什么时候会产生这样一个异常呢?

每个Thread都有一个中断状状态,默认为false。可以通过Thread对象的isInterrupted()方法来判断该线程的中断状态。可以通过Thread对象的interrupt()方法将中断状态设置为true。

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

    public class Test1 {  public static void main(String[] args) throws InterruptedException {  MyThread thread=new MyThread();  thread.start();  }  }  class MyThread extends Thread {  int i=1;  @Override  public void run() {  while (true) {  System.out.println(i);  System.out.println(this.isInterrupted());  try {  System.out.println("我马上去sleep了");  Thread.sleep(2000);  this.interrupt();  } catch (InterruptedException e) {  System.out.println("异常捕获了"+this.isInterrupted());  return;  }  i++;  }  }  }  
1
false
我马上去sleep了
2
true
我马上去sleep了
异常捕获了false 

可以看到,首先执行第一次while循环,在第一次循环中,睡眠2秒,然后将中断状态设置为true。当进入到第二次循环的时候,中断状态就是第一次设置的true,当它再次进入sleep的时候,马上就抛出了InterruptedException异常,然后被我们捕获了。然后中断状态又被重新自动设置为false了(从最后一条输出可以看出来)。

5、堵塞(blocked)
由于某种原因导致正在运行的线程让出CPU并暂停自己的执行,即进入堵塞状态。
正在睡眠:用sleep(long t) 方法可使线程进入睡眠方式。一个睡眠着的线程在指定的时间过去可进入就绪状态。
正在等待:调用wait()方法。(调用motify()方法回到就绪状态)
被另一个线程所阻塞:调用suspend()方法。(调用resume()方法恢复)

wait 放对象锁 sleep不放。sleep不出让系统资源;wait是进入线程等待池等待,出让系统资源,其他线程可以占用CPU

阻塞指的是暂停一个线程的执行以等待某个条件发生(如某资源就绪)

Java 提供了大量方法来支持阻塞,下面让我们逐一分析。

  1. sleep() 方法:sleep() 允许 指定以毫秒为单位的一段时间作为参数,它使得线程在指定的时间 
内进入阻塞状态,不能得到CPU 时间,指定的时间一过,线程重新进入可执行状态。 
  典型地,sleep() 被用在等待某个资源就绪的情形:测试发现条件不满足后,让线程阻塞一段时间后 
重新测试,直到条件满足为止。 
  2. suspend() 和 resume() 方法(已弃用)。 
  3. yield() 方法:yield() 使得线程放弃当前分得的 CPU 时间,但是不使线程阻塞,即线程仍处于 
可执行状态,随时可能再次分得 CPU 时间。调用 yield() 的效果等价于调度程序认为该线程已执行了足 
够的时间从而转到另一个线程。 
  4. wait() 和 notify() 方法:两个方法配套使用,wait() 使得线程进入阻塞状态,它有两种形式 
,一种允许指定以毫秒为单位的一段时间作为参数,另一种没有参数,前者当对应的 notify() 被调用或 
者超出指定时间时线程重新进入可执行状态,后者则必须对应的 notify() 被调用。 
  初看起来它们与 suspend() 和 resume() 方法对没有什么分别,但是事实上它们是截然不同的。区 
别的核心在于,前面叙述的所有方法,阻塞时都不会释放占用的锁(如果占用了的话),而这一对方法则 
相反。

二、线程状态的控制

Java提供了一些便捷的方法用于会线程状态的控制。

 void destroy()
          已过时。 该方法最初用于破坏该线程,但不作任何清除。它所保持的任何监视器都会保持锁定状态。不过,该方法决不会被实现。即使要实现,它也极有可能以suspend() 方式被死锁。如果目标线程被破坏时保持一个保护关键系统资源的锁,则任何线程在任何时候都无法再次访问该资源。如果另一个线程曾试图锁定该资源,则会出现死锁。这类死锁通常会证明它们自己是“冻结”的进程。有关更多信息,请参阅为何不赞成使用 Thread.stop、Thread.suspend 和 Thread.resume?。
 void interrupt()
          中断线程。
 void join()
          等待该线程终止。
 void join(long millis)
          等待该线程终止的时间最长为 millis 毫秒。
 void join(long millis, int nanos)
          等待该线程终止的时间最长为 millis 毫秒 + nanos 纳秒。
 void resume()
          已过时。 该方法只与 suspend() 一起使用,但suspend() 已经遭到反对,因为它具有死锁倾向。有关更多信息,请参阅为何不赞成使用 Thread.stop、Thread.suspend 和 Thread.resume?。
 void setDaemon(boolean on)
          将该线程标记为守护线程或用户线程。
 void setPriority(int newPriority)
          更改线程的优先级。
static void sleep(long millis)
          在指定的毫秒数内让当前正在执行的线程休眠(暂停执行),此操作受到系统计时器和调度程序精度和准确性的影响。
static void sleep(long millis, int nanos)
          在指定的毫秒数加指定的纳秒数内让当前正在执行的线程休眠(暂停执行),此操作受到系统计时器和调度程序精度和准确性的影响。
 void start()
          使该线程开始执行;Java 虚拟机调用该线程的 run 方法。
 void stop()
          已过时。 该方法具有固有的不安全性。用 Thread.stop 来终止线程将释放它已经锁定的所有监视器(作为沿堆栈向上传播的未检查ThreadDeath 异常的一个自然后果)。如果以前受这些监视器保护的任何对象都处于一种不一致的状态,则损坏的对象将对其他线程可见,这有可能导致任意的行为。stop 的许多使用都应由只修改某些变量以指示目标线程应该停止运行的代码来取代。目标线程应定期检查该变量,并且如果该变量指示它要停止运行,则从其运行方法依次返回。如果目标线程等待很长时间(例如基于一个条件变量),则应使用interrupt 方法来中断该等待。有关更多信息,请参阅为何不赞成使用 Thread.stop、Thread.suspend 和 Thread.resume?。
 void stop(Throwable obj)
          已过时。 该方法具有固有的不安全性。有关详细信息,请参阅 stop()。该方法的附加危险是它可用于生成目标线程未准备处理的异常(包括若没有该方法该线程不太可能抛出的已检查的异常)。有关更多信息,请参阅为何不赞成使用 Thread.stop、Thread.suspend 和 Thread.resume?。
 void suspend()
          已过时。 该方法已经遭到反对,因为它具有固有的死锁倾向。如果目标线程挂起时在保护关键系统资源的监视器上保持有锁,则在目标线程重新开始以前任何线程都不能访问该资源。如果重新开始目标线程的线程想在调用resume 之前锁定该监视器,则会发生死锁。这类死锁通常会证明自己是“冻结”的进程。有关更多信息,请参阅为何不赞成使用 Thread.stop、Thread.suspend 和 Thread.resume?。
static void yield()
          暂停当前正在执行的线程对象,并执行其他线程。

可以看到很多方法,已经标注为过时的,我们应该尽可能的避免使用它们,而应该重点关注start()、interrupt()、join()、sleep()、yield()等直接控制方法,和setDaemon()、setPriority()等间接控制方法。

sleep和wait区别

线程的生命周期以及java提供的方法相关推荐

  1. Core Java-多线程-线程的生命周期

    0. 在介绍线程前我们先看一下什么是进程? 进程是线程的母亲,如果在大学计算机课程里读过操作系统一定不会陌生. 所谓进程,它是计算机程序关于某数据集上的一次活动,是系统进行资源分配和调度的基本单位,是 ...

  2. Java的知识点28——线程的生命周期

    线程的生命周期 一个线程对象在它的生命周期内,需要经历5个状态. 1.  新生状态(New): 用new关键字建立一个线程对象后,该线程对象就处于新生状态.处于新生状态的线程有自己的内存空间,通过调用 ...

  3. Java并发编程的基础-线程的生命周期

    Java线程既然能够创建,那么也势必会被销毁,所以线程是存在生命周期的,那么我们接下来从线程的生命周期开始去了解线程. 线程一共有6种状态(NEW.RUNNABLE.BLOCKED.WAITING.T ...

  4. Java—线程的生命周期及线程控制方法详解

    关注微信公众号:CodingTechWork,一起学习进步. 线程生命周期5种状态 介绍   线程的生命周期经过新建(New).就绪(Runnable).运行(Running).阻塞(Bolocked ...

  5. 线程(线程基本概念、java实现多线程、使用多线程、线程的生命周期、线程同步、线程死锁)

    (一)线程基本概念 一. 程序, 进程, 线程的概念 程序: 使用某种语言编写一组指令(代码)的集合,静态的 进程: 运行的程序,表示程序一次完整的执行, 当程序运行完成, 进程也就结束了 个人电脑: ...

  6. java 多线程编程(包括创建线程的三种方式、线程的生命周期、线程的调度策略、线程同步、线程通信、线程池、死锁等)

    1 多线程的基础知识 1.1 单核CPU和多核CPU 单核CPU,其实是一种假的多线程,因为在一个时间单元内,也只能执行一个线程的任务.微观上这些程序是分时的交替运行,只不过是给人的感觉是同时运行,那 ...

  7. java main生命周期_Java从入门到入土(62)线程的生命周期

    线程是程序内部的一个顺序控制流,他具有一个特定的生命周期.在一个线程的生命周期中,他总是处于某一种状态中.线程的状态表示了线程正在进行的活动以及在这段时间内线程能完成的任务. 线程的生命周期包括五个状 ...

  8. java -- 线程的生命周期

    线程的生命周期 1.线程的生命周期线程是一个动态执行的过程,它也有一个从产生到死亡的过程. (1)生命周期的五种状态 新建(new Thread)当创建Thread类的一个实例(对象)时,此线程进入新 ...

  9. java for(o t :object) 获取顺序号_java中线程的生命周期

    线程是java中绕不过去的一个话题, 今天本文将会详细讲解java中线程的生命周期,希望可以给大家一些启发. java中Thread的状态 java中Thread有6种状态,分别是: NEW – 新创 ...

最新文章

  1. Delphi中的消息截获
  2. 第7篇-JAVA面向对象Ⅲ
  3. shell脚本if参数太多_Shell脚本用for循环遍历参数的方法技巧
  4. hdu1754(树状数组求最值问题)
  5. 时间序列研(part5)--四种典型的非平稳随机过程
  6. 进行api的HTML5inlinehook操作(飞秋官方下载)
  7. php自己创建函数,php自定义函数之内部函数
  8. shell实战训练营Day14
  9. spinlock导读
  10. 网页压缩ob_start('ob_gzhandler')
  11. 玩转vim之vim插件Ctags
  12. WebService:JAX-WS实现WebService
  13. intellij idea设置代码提示不区分大小写
  14. 台式计算机如何连接投影仪,台式机怎么接投影仪 台式机接投影仪方法【详解】...
  15. 倒写的乘法口诀表用c语言表示,乘法口诀表,C语言实现
  16. dataFrame(DF)将数据插入ES时报错 org.elasticsearch.hadoop.EsHadoopIllegalArgumentException: Cannot detect E
  17. 计算机管理员密码忘记了怎么恢复,新版tplink(tplogin.cn)管理员密码忘记了怎么办?...
  18. 计算机辅助设计学哪个软件,高校有必要进行计算机辅助设计软件的教学.pdf
  19. pyqt获得鼠标_PyQt5编程:鼠标事件
  20. linux 第十天 linuxprobe

热门文章

  1. 第05章 图形基础
  2. 【JAVA】文件储存——File
  3. 数学 立方和公式 立方差公式
  4. 黑苹果升级更新macOS 13 Ventura 问题整理
  5. 2020年百度运维工程师笔试真题(附答案)
  6. rabbitmq——交换机fanout和direct
  7. Sketch-Based Image Retrieval
  8. 《疾风》开发手记:NxOgre最新版本的搭建2011-10-20
  9. Minicom安装和使用和lte调试方法
  10. Python——利用协程实现视频的拖影效果