首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

Java并发编程:多线程如何实现阻塞与唤醒

线程的阻塞和唤醒在多线程并发过程中是一个关键点,当线程数量达到很大的数量级时,并发可能带来很多隐蔽的问题。如何正确暂停一个线程,暂停后又如何在一个要求的时间点恢复,这些都需要仔细考虑的细节。Java为我们提供了多种API来对线程进行阻塞和唤醒操作,比如suspend与resume、sleep、wait与notify以及park与unpark等等。

01

睡眠

控制线程阻塞与唤醒的最简单方式就是sleep了,Java通过sleep(n)方法能让线程进入到阻塞等待状态,直到休眠时间达到指定值后自动唤醒。该方法简单也常用,但这种方式比较死板,需要我们预先确定线程进入阻塞的时间。而有些场景实际上我们根本没办法确定睡眠时间,这是sleep方式的最大劣势。

sleep的使用很简单,下面为一个例子。让当前线程睡眠2000ms,最终输出为"Sleep time in ms = 2000"。

02

挂起与恢复

在Java发展史上曾经使用suspend()、resume()方法对于线程进行阻塞唤醒,它能够在代码中控制阻塞和唤醒的时间节点,比起sleep()方法更加灵活。比如线程启动后在某个时间点需要让它挂起,这可以使用suspend方法,而当要重新唤醒它时则使用resume方法。

下面代码为例看suspend与resume组合的实现,Thread2启动后输出"Second thread is suspended itself",接着自己将自己挂起。在等待2000ms后由主线程resume恢复,然后Thread2继续输出"Second thread runs again"。

注意:suspend(),resume(),stop()这样的方法都被标注为过期方法,因为其不会保证释放资源,容易产生死锁,所以不建议使用。

03

死锁问题

suspend与resume的组合存在很多问题,比较典型的还是死锁问题。如下代码,主要的逻辑代码是主线程启动线程mt一段时间后尝试使用suspend()让线程挂起,最后通过resume()恢复线程。但现实并不如愿,执行到suspend()时将一直卡住,你永远等不来“can you get here?”的输出。

为什么会产生上面的现象呢?其实是由死锁导致。乍一看感觉一点问题都没有,线程的任务仅仅只是简单地打印字符串。其实问题的根源隐藏得较深,主线程启动了线程mt后,线程mt开始执行execute()方法,不断打印字符串。

- END -

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20201215A0H1WD00?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券