别告诉我你只知道waitnotify,不知道parkunpark???
创始人
2024-05-07 10:08:18
0

目录

park&unpark

wait,notify 和 park,unpark的区别

park unpark 原理

先调用park的情况

先调用park,在调用unpark的情况

先调用unpark,在调用park的情况


park&unpark

park和unpark都是LockSupport的方法,park用于暂停当前线程的运行,而unpark用于恢复该线程的运行.

我们看一下代码,来看看park和unpark怎么用?

@Slf4j(topic = "c.TestParkUnPark")
public class TestParkUnPark {public static void main(String[] args) throws InterruptedException {/*** 我们这个unpark既可以在park之前调用,也可以在park之后调用* 用来恢复暂停线程的运行*/Thread t1 = new Thread(() -> {log.debug("开始");try {Thread.sleep(2000);} catch (InterruptedException e) {e.printStackTrace();}log.debug("park");LockSupport.park();//暂停当前线程log.debug("resume...");},"t1");t1.start();Thread.sleep(1000);log.debug("unPark");LockSupport.unpark(t1);//恢复t1线程的运行}
}

先调用park,在调用unpark

先调用unpark在调用park

从这里我们就可以发现与wait和notify不同的一点,就是unpark在park之前调用还是在park之后调用都能唤醒该线程,而在使用wait和notify的时候,先调用notify,后调用wait,那么不会唤醒waitSet中的线程,应为已经错过通知的时间了,不会唤醒.

这里我总结一下wait,notify 和 park,unpark的区别

wait,notify 和 park,unpark的区别

  • wait,notify是Object的方法,而park,unpark是LockSupport的方法
  • wait,notify必须北河 Object Monitor一起使用,而park,unpark不需要
  • park&unpark是以线程为单位来[阻塞]和[唤醒]线程的,而notify只能随机唤醒一个等待线程,notifyAll是唤醒所有等待线程,不那么精确.
  • park &unpark 可以先调用unpark,而wait,notify不能先notify.

park unpark 原理

每一个线程都有一个parker对象,由三部分组成_counter(标志位),_condition(等待队列),_mutex(对象里面有等待队列)

我们可以打一个比喻.我们把线程当做一个旅游的人,Parker就像他随身携带的背包,条件变量就相当于背包中的帐篷,_counter就相当于背包中的备用干粮

  • 调用park 就是要看当前的旅人要不要停下来去休息
    • 如果备用干粮充足(counter为1)那么就不需要停留,继续前进
    • 如果备用干粮耗尽(counter为0)那么就需要去condition帐篷(等待队列)休息
  • 调用unpark,就相当于让干粮(counter重置为1)充足
    • 如果这时旅人还在帐篷中(等待队列condition),那么就唤醒他继续前进
    • 如果这时旅人还在前进,当下次调用park的时候,不休息,仅仅消耗干粮(counter'重置0),不需停留继续前进.
      • 背包容量有效,多次调用unpark只会补充一份备用干粮

先调用park的情况

先调用park,在调用unpark的情况

先调用unpark,在调用park的情况

总结一下 :

  • 如果调用的是park,先会去检查counter
    • 如果counter为0,那么该线程获得互斥锁mutex,去mutex锁对象中的队列_cond中阻塞等待,再将counter置为0
    • 如果counter为1,那么线程无需阻塞,线程继续运行,然后将counter置为0
  • 如果调用的是unpark
    • 如果counter为0,就会将counter置为1,然后唤醒在等待队列中阻塞的线程
    • 如果此时线程还在继续运行,当下次在调用park的时候,检查counter为1,无需停留,继续运行,然后将counter置为0

另外注意 ,counter只有两种状态0,1多次调用unpark还是为状态还是为1

参考 : 黑马程序员 Java并发编程

上一篇:C++中的继承

下一篇:sql练习题3

相关内容

热门资讯

【NI Multisim 14...   目录 序言 一、工具栏 🍊1.“标准”工具栏 🍊 2.视图工具...
银河麒麟V10SP1高级服务器... 银河麒麟高级服务器操作系统简介: 银河麒麟高级服务器操作系统V10是针对企业级关键业务...
不能访问光猫的的管理页面 光猫是现代家庭宽带网络的重要组成部分,它可以提供高速稳定的网络连接。但是,有时候我们会遇到不能访问光...
AWSECS:访问外部网络时出... 如果您在AWS ECS中部署了应用程序,并且该应用程序需要访问外部网络,但是无法正常访问,可能是因为...
Android|无法访问或保存... 这个问题可能是由于权限设置不正确导致的。您需要在应用程序清单文件中添加以下代码来请求适当的权限:此外...
AWSElasticBeans... 在Dockerfile中手动配置nginx反向代理。例如,在Dockerfile中添加以下代码:FR...
北信源内网安全管理卸载 北信源内网安全管理是一款网络安全管理软件,主要用于保护内网安全。在日常使用过程中,卸载该软件是一种常...
ASM贪吃蛇游戏-解决错误的问... 要解决ASM贪吃蛇游戏中的错误问题,你可以按照以下步骤进行:首先,确定错误的具体表现和问题所在。在贪...
AsusVivobook无法开... 首先,我们可以尝试重置BIOS(Basic Input/Output System)来解决这个问题。...
月入8000+的steam搬砖... 大家好,我是阿阳 今天要给大家介绍的是 steam 游戏搬砖项目,目前...