首页 > 编程知识 正文

多线程有几种状态,线程状态是5种还是6种

时间:2023-05-04 20:12:35 阅读:160586 作者:4039

Java中线程的生命周期大致分为5种状态。

1. 新建(NEW):已创建新的线程对象。

2. 可运行(RUNNABLE):创建线程对象后,其他线程(如main线程)调用了该对象的start ()方法。 此状态的线程位于可执行线程池中,等待在线程调度中进行选择,以获得cpu的使用权。

3. 运行(RUNNING):可执行状态(runnable )的线程获得cpu时间片),执行程序代码。

4. 阻塞(BLOCKED):阻塞状态是指线程由于某种原因放弃了cpu使用权,也就是让出cpu timeslice,暂时停止的状态。 在线程进入可执行(runnable )状态之前,无法再次获取cpu timeslice并转换到可执行(running )状态。 阻塞的情况分为三种:

(一) .块等待)执行(running )的线程执行o.wait )方法,JVM将其线程放入等待队列(waitting queue )。

(二) .同步阻断:执行(running )的线程获取对象的同步锁时,如果该同步锁被其他线程占用,JVM会将其线程放入锁池(lock pool )。

(三)其他块)执行中(running )的线程执行thread.sleep(longms )或者t.join )方法,或者I/O请求被发行时,JVM会屏蔽该线程当sleep (状态超时,join )等待线程完成或超时,或者I/O处理完成时,线程将再次进入可执行状态。 5. 死亡(DEAD):线程run (,main ) (或run ) )方法已完成或异常终止,因此线程将终止生命周期。 死亡线程不能再次复活。

一.线程的状态图

二.初始状态

安装Runnable接口,继承Thread就可以得到线程类,出现new的实例时,线程处于初始状态三.可运行状态

可行状态只是说你有资格执行,如果调度程序不选择你,你永远都是可行状态。 线程开始) )方法,使其处于可执行状态。 当前线程的sleep (方法结束,其他线程的join )结束,等待用户输入完成,一个线程将获得对象锁,这些线程也将变为可执行状态。 当前线程的时间片不再可用,因此调用当前线程的yield ()方法以使当前线程可执行。 获得对象锁后,锁定池中的线程将处于可执行状态。四.运行状态

线程调度程序从可执行池中选择线程作为当前线程时的线程状态。 这也是线程进入运行状态的唯一途径。五.死亡状态

线程的run ) )方法完成时,或者主线程的main ) )方法完成时,我们认为它已经死了。 此线程对象可能是活动的,但已经不是单独运行的线程。 如果线程死了,就不能复活。 在死线程上调用start ()方法时,会抛出Java.lang.illegalthreadstateexception异常。六.阻塞状态

当前线程t调用Thread.sleep ()方法,当前线程处于阻塞状态。 当前线程上正在运行的其他线程t2调用join ()方法,当前线程处于阻塞状态。 在等待用户输入时,当前线程处于阻塞状态。七.等待队列(本是Object里的方法,但影响了线程)

在调用obj的wait (,notify )方法之前,必须获取obj锁。 这意味着必须在synchronized )、obj )代码部分中进行编写。 队列的步骤和图线程1获得了对象a的锁定,并正在使用对象a。 线程1调用对象a的wait (方法)。 线程1解除对象a的锁定,立即进入队列。 池中的对象争夺对象a的锁定。 线程5获得对象a的锁定,进入同步块,并使用对象a。 线程5调用对象a的notifyAll ()方法,调用所有线程,所有线程进入锁定池。 |||||线程5调用对象a的notify )方法来调用不知道要调用谁的线程。 被唤醒的线程进入洛克池。 notifyAll ) )方法的synchronized结束,线程5解除对象a的锁定。 锁池中的线程会争夺对象锁,但不知道线程1什么时候能被夺取。 |||||在锁定池的步骤6中醒来的线程一起争夺对象锁。

八.锁池状态

当当前线程尝试调用对象a的同步方法时,它发现对象a的锁被另一个线程占用,此时当前线程处于锁池状态。 简而言之,锁定池中有一个线程想争夺目标锁定。 当一个线程1被另一个线程2唤醒时,一个线程进入锁池状态,争夺对象锁。 锁定池是一个仅在同步环境中存在的概念,对象对应于锁定池。九.几个方法的比较

thread.sleep(longmillis )始终由当前线程调用此方法,以使当前线程进入块中,但不会解除对象锁定

,millis后线程自动苏醒进入可运行状态。作用:给其它线程执行机会的最佳方式。Thread.yield(),一定是当前线程调用此方法,当前线程放弃获取的cpu时间片,由运行状态变会可运行状态,让OS再次选择线程。作用:让相同优先级的线程轮流执行,但并不保证一定会轮流执行。实际中无法保证yield()达到让步目的,因为让步的线程还有可能被线程调度程序再次选中。Thread.yield()不会导致阻塞。t.join()/t.join(long millis),当前线程里调用其它线程1的join方法,当前线程阻塞,但不释放对象锁,直到线程1执行完毕或者millis时间到,当前线程进入可运行状态。obj.wait(),当前线程调用对象的wait()方法,当前线程释放对象锁,进入等待队列。依靠notify()/notifyAll()唤醒或者wait(long timeout)timeout时间到自动唤醒。obj.notify()唤醒在此对象监视器上等待的单个线程,选择是任意性的。notifyAll()唤醒在此对象监视器上等待的所有线程。

 

线程状态:

    

线程从创建、运行到结束总是处于下面五个状态之一:新建状态、就绪状态、运行状态、阻塞状态及死亡状态。


    1.新建状态(New): 
        当用new操作符创建一个线程时, 例如new Thread(r),线程还没有开始运行,此时线程处在新建状态。 当一个线程处于fdym状态时,程序还没有开始运行线程中的代码

     2.就绪状态(Runnable)

        一个新创建的线程并不自动开始运行,要执行线程,必须调用线程的start()方法。当线程对象调用start()方法即启动了线程,start()方法创建线程运行的系统资源,并调度线程运行run()方法。当start()方法返回后,线程就处于就绪状态。

        处于就绪状态的线程并不一定立即运行run()方法,线程还必须同其他线程竞争CPU时间,只有获得CPU时间才可以运行线程。因为在单CPU的计算机系统中,不可能同时运行多个线程,一个时刻仅有一个线程处于运行状态。因此此时可能有多个线程处于就绪状态。对多个处于就绪状态的线程是由Java运行时系统的线程调度程序(thread scheduler)来调度的。


    3.运行状态(Running)

        当线程获得CPU时间后,它才进入运行状态,真正开始执行run()方法.

    4. 阻塞状态(Blocked)

        线程运行过程中,可能由于各种原因进入阻塞状态:
        1>线程通过调用sleep方法进入睡眠状态;
        2>线程调用一个在I/O上被阻塞的操作,即该操作在输入输出操作完成之前不会返回到它的调用者;
        3>线程试图得到一个锁,而该锁正被其他线程持有;
        4>线程在等待某个触发条件;
        ......           
        所谓阻塞状态是正在运行的线程没有运行结束,暂时让出CPU,这时其他处于就绪状态的线程就可以获得CPU时间,进入运行状态。

    5. 死亡状态(Dead)

        有两个原因会导致线程死亡:
         1) run方法正常退出而自然死亡,
         2) 一个未捕获的异常终止了run方法而使线程猝死。
        为了确定线程在当前是否存活着(就是要么是可运行的,要么是被阻塞了),需要使用isAlive方法。如果是可运行或被阻塞,这个方法返回true; 如果线程仍旧是new状态且不是可运行的, 或者线程死亡了,则返回false.

 

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。