• Java线程的生命周期(转)


    Java线程的生命周期

    Java线程的生命周期

    一个线程的产生是从我们调用了start方法开始进入Runnable状态,即可以被调度运行状态,并没有真正开始运行,调度器可以将CPU分配给它,使线程进入Running状态,真正运行其中的程序代码。线程在运行过程中,有以下几个可能的去向:

    (1)调度器在某个线程的执行过程中将CPU分配给了其它线程,则这个线程又变为Runnable状态,等待被调度。

    (2)调度器将CPU分配给了该线程,执行过程中没有遇到任何阻隔,运行完成直接结束,也就是run()方法执行完毕。

    (3)线程在执行过程中请求锁,却得不到,这时候它要进入lock pool中等待对象的锁,等到锁后又会进入Runnable状态,可以被调度运行。

    (4)线程在执行过程中遇到wait()方法,它会被放入wait pool中等待,直到有notify()或interrupt()方法执行,它才会被唤醒或打断进入lock pool开始等待对象锁,等到锁后进入Runnable状态。

    推荐在run方法中使用控制循环条件的方式来结束一个线程。

    wait:告诉当前线程放弃对象锁并进入等待状态,直到其他线程进入同一对象锁并调用notify为止。

    notify:唤醒同一对象锁中调用wait的第一个线程。

    notifyAll:唤醒同一对象锁中调用wait的所有线程,具有最高优先级的线程首先被唤醒并执行。

    yield:如果知道已经完成了在run()方法的循环的一次迭代过程中所需要的工作,就可以给线程调度一个机制暗示:我的工作已经做的差不多了,可以让给别的线程使用CPU了。通过调用yield()来实现。
    当调用yield时,你也是在建议具有相同优先级的其他线程可以运行。
    对于任何重要的控制或在调整应用时,都不恩那个依赖于yield。实际上,yield经常被误用。
    (yield并不意味着退出和暂停,只是,告诉线程调度如果有人需要,可以先拿去,我过会再执行,没人需要,我继续执行)
    调用yield的时候锁并没有被释放。

    interrupt简述

    interrupt() 方法只是改变中断状态而已,它不会中断一个正在运行的线程。这一方法实际完成的是,给受阻塞的线程发出一个中断信号,这样受阻线程就得以退出阻塞的状态。 更确切的说,如果线程被Object.wait, Thread.join和Thread.sleep三种方法之一阻塞,此时调用该线程的interrupt()方法,那么该线程将抛出一个 InterruptedException中断异常(该线程必须事先预备好处理此异常),从而提早地终结被阻塞状态。如果线程没有被阻塞,这时调用 interrupt()将不起作用,直到执行到wait(),sleep(),join()时,才马上会抛出 InterruptedException。

    线 程A在执行sleep,wait,join时,线程B调用线程A的interrupt方法,的确这一个时候A会有 InterruptedException 异常抛出来。但这其实是在sleep,wait,join这些方法内部会不断检查中断状态的值,而自己抛出的InterruptedException。 如果线程A正在执行一些指定的操作时如值,for,while,if,调用方法等,不会去检查中断状态,则线程A不会抛出 InterruptedException,而会一直执行着自己的操作。

    注意:

    当线程A执行到wait(),sleep(),join()时,抛出InterruptedException后,中断状态已经被系统复位了,线程A调用Thread.interrupted()返回的是false。

    如果线程被调用了interrupt(),此时该线程并不在wait(),sleep(),join()时,下次执行wait(),sleep(),join()时,一样会抛出InterruptedException,当然抛出后该线程的中断状态也会被系统复位。

    1. sleep() &interrupt()

    线程A正在使用sleep()暂停着: Thread.sleep(100000),如果要取消它的等待状态,可以在正在执行的线程里(比如这里是B)调用a.interrupt()[a是线程A对应到的Thread实例],令线程A放弃睡眠操作。即,在线程B中执行a.interrupt(),处于阻塞中的线程a将放弃睡眠操作。

    当在sleep中时线程被调用interrupt()时,就马上会放弃暂停的状态并抛出InterruptedException。抛出异常的,是A线程。

    2. wait() &interrupt()

    线程A调用了wait()进入了等待状态,也可以用interrupt()取消。不过这时候要注意锁定的问题。线程在进入等待区,会把锁定解除,当对等待中的线程调用interrupt()时,会先重新获取锁定,再抛出异常。在获取锁定之前,是无法抛出异常的。

    3. join() &interrupt()

    当线程以join()等待其他线程结束时,当它被调用interrupt(),它与sleep()时一样,会马上跳到catch块里.。

    注意,调用的interrupt()方法,一定是调用被阻塞线程的interrupt方法。如在线程a中调用线程t.interrupt()。

    http://www.open-open.com/lib/view/open1417421714612.html

  • 相关阅读:
    #Laravel笔记# 使用SMTP发送邮件功能
    #Laravel笔记# 监听事件
    idea 常见问题
    python常见函数汇总
    双DNN排序模型:在线知识蒸馏在爱奇艺推荐的实践
    机器学习算法GBDT
    Hive表数据同步到es
    目标检测资料
    zeppelin的介绍与使用
    Java汉字获取拼音、笔划、偏旁部首
  • 原文地址:https://www.cnblogs.com/softidea/p/4280542.html
Copyright © 2020-2023  润新知