前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Java 并发编程:多线程如何实现阻塞与唤醒

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

原创
作者头像
码农架构
修改2020-12-16 10:10:05
1K0
修改2020-12-16 10:10:05
举报
文章被收录于专栏:码农架构

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

睡眠

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

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

挂起与恢复

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

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

 死锁问题

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

问题就出现在System.out.println,由于println被声明为一个同步方法,执行时将对System类的out(PrintStream类的一个实例)单例属性加同步锁。而suspend()方法挂起线程但并不释放锁,在线程mt被挂起后主线程调用System.out.println同样需要获取System类ut对象的同步锁才能打印“can you get here?”。主线程就一直在等待同步锁而mt线程不释放锁,这就导致了死锁的产生。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 睡眠
  • 挂起与恢复
  •  死锁问题
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档