【多线程:Park&Unpark】

简介: 【多线程:Park&Unpark】

【多线程:Park&Unpark】

01.介绍

基本使用

// 暂停当前线程 
LockSupport.park(); 
// 恢复某个线程的运行 
LockSupport.unpark(暂停线程对象)

当在某线程使用LockSupport.park();后此线程变为WATING状态

02.例子

@Slf4j(topic = "c.TestParkUnpark")
public class TestParkUnpark {
    public static void main(String[] args) {
        Thread t1 = new Thread(() -> {
            log.debug("start...");
            sleep(1);
            log.debug("park...");
            LockSupport.park();
            log.debug("resume...");
        }, "t1");
        t1.start();

        sleep(2);
        log.debug("unpark...");
        LockSupport.unpark(t1);
    }
}

结果

17:22:16.403 c.TestParkUnpark [t1] - start...
17:22:17.412 c.TestParkUnpark [t1] - park...
17:22:18.402 c.TestParkUnpark [main] - unpark...
17:22:18.402 c.TestParkUnpark [t1] - resume...

解释
可以看出我们在1s时LockSupport.park();暂停了线程t1 在2s时LockSupport.unpark(t1);把t1线程恢复

注意

如果我们此时在1s时恢复t1线程,2s时再暂停t1线程会怎么样?

@Slf4j(topic = "c.TestParkUnpark")
public class TestParkUnpark {
    public static void main(String[] args) {
        Thread t1 = new Thread(() -> {
            log.debug("start...");
            sleep(2);
            log.debug("park...");
            LockSupport.park();
            log.debug("resume...");
        }, "t1");
        t1.start();

        sleep(1);
        log.debug("unpark...");
        LockSupport.unpark(t1);
    }
}

结果

17:27:11.949 c.TestParkUnpark [t1] - start...
17:27:12.959 c.TestParkUnpark [main] - unpark...
17:27:13.958 c.TestParkUnpark [t1] - park...
17:27:13.958 c.TestParkUnpark [t1] - resume...

解释
可以看出我们先unpark再park,t1线程还是正常运行,和我们对wait/notify的理解不一样

03.特点

LockSupport的park/unpark与Object的wait/notify相比

1.wait notify和notifyAll必须配合Object Monitor一起使用也就是必须在重量级锁的情况下才可以用,而park unpark不需要
2.park unpark是以线程为单位来阻塞和唤醒线程 标签可以精确唤醒指定等待线程,而notify只能随机唤醒一个等待线程 notifyAll则是唤醒全部等待线程,不精确
3.park unpark可以先unpark,但是 wait notify不能先notify

04.原理

每个线程都有自己的一个Parker对象,由三部分组成_counter, _ cond和_mtuex,打个比喻
线程就像一个旅行的人,Parker是它随身携带背包,条件变量就好比背包中的帐篷,_ counter就好比背包中的备用干粮(0为耗尽,1为充足)
调用park就是要看需不需要停下来休息

如果备用干粮耗尽,则去帐篷中休息
如果备用干粮充足,那么不需要停留 继续前进

调用unpark,就好比令干粮充足

如果此时线程还在帐篷 那么久唤醒他 继续前行
如果此时线程还在运行 那么下次他调用park时 仅是消耗备用干粮 不需停留继续前进
        因为背包空间有限 多次调用unpark仅会补充一份备用干粮


前提:还没有park,探究park过程的变化

1.当前线程调用park方法
2.检查_counter 本情况为0 此时 获得_mutex互斥锁
3.线程进入_cond条件变量阻塞
4.设置_counter=0


前提:此时已经park过了,探究unpark过程的变化

1.调用unpark(Thread_0)方法,设置_counter为1
2.唤醒_cond条件变量中的Thread_0
3.Thread_0恢复运行
4.设置_counter为0


前提:探究先unpark后park的情况

1.调用unpark(Thread_0)方法,设置_counter为1
2.当前线程调用park方法
3.检查_counter 本情况为1 此时线程无需阻塞 继续运行
4.设置_counter为0
目录
相关文章
|
安全 Java C++
JUC在深入面试题——三种方式实现线程等待和唤醒(wait/notify,await/signal,LockSupport的park/unpark)
JUC在深入面试题——三种方式实现线程等待和唤醒(wait/notify,await/signal,LockSupport的park/unpark)
159 1
JUC在深入面试题——三种方式实现线程等待和唤醒(wait/notify,await/signal,LockSupport的park/unpark)
|
3天前
|
Java 数据库 Android开发
【专栏】Kotlin在Android开发中的多线程优化,包括线程池、协程的使用,任务分解、避免阻塞操作以及资源管理
【4月更文挑战第27天】本文探讨了Kotlin在Android开发中的多线程优化,包括线程池、协程的使用,任务分解、避免阻塞操作以及资源管理。通过案例分析展示了网络请求、图像处理和数据库操作的优化实践。同时,文章指出并发编程的挑战,如性能评估、调试及兼容性问题,并强调了多线程优化对提升应用性能的重要性。开发者应持续学习和探索新的优化策略,以适应移动应用市场的竞争需求。
|
3天前
|
Java 数据库
【Java多线程】对线程池的理解并模拟实现线程池
【Java多线程】对线程池的理解并模拟实现线程池
16 1
|
1天前
|
Python
|
2天前
|
监控 Java 测试技术
在多线程开发中,线程死循环可能导致系统资源耗尽,影响应用性能和稳定性
【5月更文挑战第16天】在多线程开发中,线程死循环可能导致系统资源耗尽,影响应用性能和稳定性。为解决这一问题,建议通过日志记录、线程监控工具和堆栈跟踪来定位死循环;处理时,及时终止线程、清理资源并添加错误处理机制;编码阶段要避免无限循环,正确使用同步互斥,进行代码审查和测试,以降低风险。
18 3
|
3天前
|
设计模式 消息中间件 安全
【Java多线程】关于多线程的一些案例 —— 单例模式中的饿汉模式和懒汉模式以及阻塞队列
【Java多线程】关于多线程的一些案例 —— 单例模式中的饿汉模式和懒汉模式以及阻塞队列
12 0
|
3天前
|
Java
【Java多线程】分析线程加锁导致的死锁问题以及解决方案
【Java多线程】分析线程加锁导致的死锁问题以及解决方案
25 1
|
3天前
|
存储 缓存 安全
【Java多线程】线程安全问题与解决方案
【Java多线程】线程安全问题与解决方案
22 1
|
3天前
|
Java 调度
【Java多线程】线程中几个常见的属性以及状态
【Java多线程】线程中几个常见的属性以及状态
13 0
|
3天前
|
Java 调度
【Java多线程】对进程与线程的理解
【Java多线程】对进程与线程的理解
13 1