线程的生命周周期和基本方法

线程的生命周周期和基本方法

生命周期

​ 线程的生命周期分为5种,新建(New)、就绪(Runnable)、运行(Running)、堵塞(Blocked)和死亡(Dead)。

​ 当我们调用run方法创建一个线程的时候,这时候现场就会进入新建状态。

​ 调用start方法的时候,线程就会进入就绪状态。

​ 处于就绪状态的线程就会等待线程获取CPU资源,当获取到cpu资源资源就会调用run方法进入执行状态

​ 当正在执行的线程执行yield方法或者失去了处理器资源的时候就会进入就绪状态

​ 正在执行的线程在执行sleep方法、I/O堵塞、等待同步锁、等待通知、调用suspend方法等操作后,就会进入堵塞状态,进入Blocked池。

​ 堵塞状态的线程出现sleep时间到了,I/O方法返回、获取同步锁,接到通知,调用susume方法等情况就会进入就绪状态,等待CPU时间片的轮询,该线程获取到CPU资源后,就会进入运行状态。

处于运行状态的线程,在call方法或者run方法执行完毕、调用stop方法或者线程发生异常就会进入死亡状态

新建状态New

​ 在Java使用new关键字创建一个线程,那么这个线程就处于新创建状态、在创建线程的时候主要就是为线程分配内存,并初始化成员变量信息。

就绪状态Runnable

​ 新创建的线程在调用了start方法就代表进入了就绪状态,此时JVM虚拟机完成了方法调用栈还有程序计数器的创建,等待线程的调度和执行,

运行状态Running

​ 在就绪状态的线程竞争到CPU的使用权并开始执行run方法就会进入运行状态,处于运行状态的主要任务就是执行run方法的中的代码。

堵塞状态Blocked

​ 运行中的线程主动或被动放弃了CPU的使用权并停止运行,此时这个线程就会进入堵塞状态。

​ 堵塞状态主要分为3种

​ **等待堵塞:**在运行状态的线程调用o.wait方法时,JVM会把线程放入等待队列中,线程转为堵塞状态。

​ **同步堵塞:**在运行状态的线程尝试获取正在被其他线程占用的对象同步锁的时候,JVM就会把该线程放入到 同步锁中,此时线程会转换为堵塞状态。

​ **其他堵塞:**运行中的线程执行Thread.sleep、Thread.join或者发出I/O操作请求的时候,JVM就会进入堵塞状态,直到sleep状态超时、join等待线程终止或者超时I\O处理完毕,线程才可以重新转换为可运行状态。

线程死亡Dead

​ 只有3种方式结束才能进入死亡状态

​ **线程正常结束:**run方法或者call方法执行完成

​ **线程异常退出:**运行时线程抛出Error或者未捕获Exception,线程异常退出

​ **线程手动结束:**调用线程的stop方法。

​ 调用此方法会瞬间释放线程占用的同步对象锁、导致锁混乱和死锁,不推荐

线程的基本方法

线程等待 wait

​ 调用wait方法会进入waiting状态,只有等待其他线程通知或者被中断后才会返回。在调用wait方法会释放对象的锁,所以wait方法一半使用在同步方法或者同步代码块中。

线程睡眠 sleep

​ 调用sleep方法会让当前线程休眠,与wait方法不同的是,sleep方法不会释放当前线程所占有的锁,会导致线程进入TIMED——WATIING装啊题,而wait方法进入WAITING状态。

线程让步 yield

​ 调用yield方法就会释放cpu的使用权,并与其他线程一起竞争CPU的使用权。

​ 在一般情况下,优先级高的线程更有可能竞争到CPU时间片,但这不是绝对的。因为有的操作系统对优先级不敏感。

线程中断 Interrupt

​ **interrput是向线发起一个终止通知信号,**会影响该线程内部的一个中断标识位置,线程本体不会因为调用了interrput方法改变状态,状态的具体变化需要等待接收中断标识的程序的最终处理结果来判定。

处于running状态的线程不会因为调用了interrupt方法而终止,它仅仅是改变了内部维护的中断标识

如果调用sleep方法使线程进入timed—waiting状态,这时候调用interrupt方法会抛出InterruptedException,会使线程提前解除TIMED-WATING

​ sleep方法抛出interruptException 的主要目的就有一个,就是让sleep提前醒来

​ 当线程正在等待、休眠或者以其他方式被占用并在**线程活动之前或者中断(就是变为runnable之前或者变为runnable的途中也就是不处于runnable状态)**的时候抛出

​ 也就是说线程在Blocked和waiting和timed_waiting状态或者从这三种状态转换为runnable状态的过程中如果被中断会抛出interruptException

​ 中断状态是线程一个固有的标识位,可以通过此标识位安全终止线程。比如,想要去终止一个线程,可以先调用interrupt方法,然后在线程的run方法中根据isInterrupt方法的返回状态值安全的终止线程。

线程加入 join

​ join方法用于等待其他线程终止,如果在当前线程中调用一个线程的join方法,则当前线程会进入堵塞状态,等待另一个线程运行结束,当前线程会从堵塞状态进入到就绪状态,等待CPU的使用权。在狠毒情况下,主线程生产并启动了子线程,需要等待子线程的返回结果并处理收集和处理再退出,这时候就要用到join方法。

线程唤醒 notify

​ Object类有一个notify方法,用于唤醒在此对象监视器上等待的一个线程,如果有很多个对象都在这个对象上等待那么就随机唤醒一个。

如果一个对象执行了wait方法,那么这个线程就会进入等待状态,等待状态下的线程必须要被其他线程调用notify方法才能被唤醒

全部线程唤醒notifyAll

​ 和notify一样,唯一不同的是他是唤醒全部线程

后台守护线程 setDaemon

​ 该线程是后台线程,后台线程有一个特性,就是为所有用户线程提供一个服务,在没有用户线程可以服务的时候,它就会自动离开。

​ 后台守护线程是JVM级别的,比如JVM垃圾回收就是一个典型的守护线程,守护线程不依赖终端,依赖JVM,与jVM同生共死,当JVM中所有线程都是守护线程的时候JVM就可以退出了,若有一个线程不是,那么JVM就不能退出。

Sleep和wait的区别

​ sleep属于Thead的类,wait属于Object类。

​ sleep方法暂停执行的指定时间,在指定的时间过后又会自动恢复运行状态

​ 调用sleep方法不会释放锁

​ 调用wait会释放锁,进入等待此对象的等待锁池,只有针对调用此对象的notify方法后改线程才能进入对象锁池准备获取对象锁,并进入运行状态。

Start和run方法的区别

​ start方法用于启动线程,真正的实现了多线程运行,在调用start方法后,线程会在后台执行,无需等待run方法体的代码执行完毕,就可以执行下面的代码。

​ 在通过调用Thread类的start方法启动一个线程,此线程处于就绪状态,并没有直接运行。

​ run方法叫做线程体,包含了要执行的线程的逻辑代码,在调用run方法后会进入运行状态,开始执行run方法体的代码,在run方法结束后,该线程也就终止了,CPU就在此调度其他线程。

终止线程的4种方法

1.正常运行结束

​ 指的是线程体的代码运行结束,线程自动结束

2.使用标志退出线程

​ 一般情况下,在run方法执行完线程就会结束,但是有些线程需要长时间运行的时候,需要满足一些特性才能退出,所以就需要boolean类型作为标志来判断是否可以退出线程

3.使用Interrupt方法终止线程

​ 当线程线程处于堵塞状态,在调用线程的interrupt方法会抛出INterruptException异常,然后通过break跳出检测循环,结束这个线程的运行, 一定要先捕获InterruptException然后在break;

4使用stop

​ 使用stop结束线程是十分危险的,因为该方法会瞬间释放该线程占用的同步对象锁,导致锁混乱和死锁

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

哇塞大嘴好帅(DaZuiZui)

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值