【多线程: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)
241 1
JUC在深入面试题——三种方式实现线程等待和唤醒(wait/notify,await/signal,LockSupport的park/unpark)
|
4月前
|
Java 开发者
Java多线程编程中的常见误区与最佳实践####
本文深入剖析了Java多线程编程中开发者常遇到的几个典型误区,如对`start()`与`run()`方法的混淆使用、忽视线程安全问题、错误处理未同步的共享变量等,并针对这些问题提出了具体的解决方案和最佳实践。通过实例代码对比,直观展示了正确与错误的实现方式,旨在帮助读者构建更加健壮、高效的多线程应用程序。 ####
|
4月前
|
安全 Java UED
深入浅出Java多线程编程
【10月更文挑战第40天】在Java的世界中,多线程是提升应用性能和响应能力的关键。本文将通过浅显易懂的方式介绍Java中的多线程编程,从基础概念到高级特性,再到实际应用案例,带你一步步深入了解如何在Java中高效地使用多线程。文章不仅涵盖了理论知识,还提供了实用的代码示例,帮助你在实际开发中更好地应用多线程技术。
118 5
|
1月前
|
Linux
Linux编程: 在业务线程中注册和处理Linux信号
本文详细介绍了如何在Linux中通过在业务线程中注册和处理信号。我们讨论了信号的基本概念,并通过完整的代码示例展示了在业务线程中注册和处理信号的方法。通过正确地使用信号处理机制,可以提高程序的健壮性和响应能力。希望本文能帮助您更好地理解和应用Linux信号处理,提高开发效率和代码质量。
49 17
|
1月前
|
Linux
Linux编程: 在业务线程中注册和处理Linux信号
通过本文,您可以了解如何在业务线程中注册和处理Linux信号。正确处理信号可以提高程序的健壮性和稳定性。希望这些内容能帮助您更好地理解和应用Linux信号处理机制。
60 26
|
3月前
|
存储 安全 Java
Java多线程编程秘籍:各种方案一网打尽,不要错过!
Java 中实现多线程的方式主要有四种:继承 Thread 类、实现 Runnable 接口、实现 Callable 接口和使用线程池。每种方式各有优缺点,适用于不同的场景。继承 Thread 类最简单,实现 Runnable 接口更灵活,Callable 接口支持返回结果,线程池则便于管理和复用线程。实际应用中可根据需求选择合适的方式。此外,还介绍了多线程相关的常见面试问题及答案,涵盖线程概念、线程安全、线程池等知识点。
287 2
|
4月前
|
设计模式 Java 开发者
Java多线程编程的陷阱与解决方案####
本文深入探讨了Java多线程编程中常见的问题及其解决策略。通过分析竞态条件、死锁、活锁等典型场景,并结合代码示例和实用技巧,帮助开发者有效避免这些陷阱,提升并发程序的稳定性和性能。 ####
|
4月前
|
缓存 Java 开发者
Java多线程编程的陷阱与最佳实践####
本文深入探讨了Java多线程编程中常见的陷阱,如竞态条件、死锁和内存一致性错误,并提供了实用的避免策略。通过分析典型错误案例,本文旨在帮助开发者更好地理解和掌握多线程环境下的编程技巧,从而提升并发程序的稳定性和性能。 ####
|
3月前
|
缓存 Java 调度
多线程编程核心:上下文切换深度解析
在现代计算机系统中,多线程编程已成为提高程序性能和响应速度的关键技术。然而,多线程编程中一个不可避免的概念就是上下文切换(Context Switching)。本文将深入探讨上下文切换的概念、原因、影响以及优化策略,帮助你在工作和学习中深入理解这一技术干货。
70 10
|
3月前
|
安全 算法 Java
Java多线程编程中的陷阱与最佳实践####
本文探讨了Java多线程编程中常见的陷阱,并介绍了如何通过最佳实践来避免这些问题。我们将从基础概念入手,逐步深入到具体的代码示例,帮助开发者更好地理解和应用多线程技术。无论是初学者还是有经验的开发者,都能从中获得有价值的见解和建议。 ####

热门文章

最新文章