【多线程: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)
197 1
JUC在深入面试题——三种方式实现线程等待和唤醒(wait/notify,await/signal,LockSupport的park/unpark)
|
24天前
|
存储 监控 Java
Java多线程优化:提高线程池性能的技巧与实践
Java多线程优化:提高线程池性能的技巧与实践
48 1
|
7天前
|
Java 数据库 Android开发
一个Android App最少有几个线程?实现多线程的方式有哪些?
本文介绍了Android多线程编程的重要性及其实现方法,涵盖了基本概念、常见线程类型(如主线程、工作线程)以及多种多线程实现方式(如`Thread`、`HandlerThread`、`Executors`、Kotlin协程等)。通过合理的多线程管理,可大幅提升应用性能和用户体验。
25 15
一个Android App最少有几个线程?实现多线程的方式有哪些?
|
9天前
|
Java 数据库 Android开发
一个Android App最少有几个线程?实现多线程的方式有哪些?
本文介绍了Android应用开发中的多线程编程,涵盖基本概念、常见实现方式及最佳实践。主要内容包括主线程与工作线程的作用、多线程的多种实现方法(如 `Thread`、`HandlerThread`、`Executors` 和 Kotlin 协程),以及如何避免内存泄漏和合理使用线程池。通过有效的多线程管理,可以显著提升应用性能和用户体验。
29 10
|
16天前
|
存储 Ubuntu Linux
C语言 多线程编程(1) 初识线程和条件变量
本文档详细介绍了多线程的概念、相关命令及线程的操作方法。首先解释了线程的定义及其与进程的关系,接着对比了线程与进程的区别。随后介绍了如何在 Linux 系统中使用 `pidstat`、`top` 和 `ps` 命令查看线程信息。文档还探讨了多进程和多线程模式各自的优缺点及适用场景,并详细讲解了如何使用 POSIX 线程库创建、退出、等待和取消线程。此外,还介绍了线程分离的概念和方法,并提供了多个示例代码帮助理解。最后,深入探讨了线程间的通讯机制、互斥锁和条件变量的使用,通过具体示例展示了如何实现生产者与消费者的同步模型。
|
24天前
|
监控 安全 Java
Java多线程调试技巧:如何定位和解决线程安全问题
Java多线程调试技巧:如何定位和解决线程安全问题
71 2
【多线程面试题 一】、 创建线程有哪几种方式?
创建线程的三种方式包括继承Thread类、实现Runnable接口和实现Callable接口,其中Runnable和Callable接口方式更受推荐,因为它们允许多重继承并更好地体现面向对象思想。
|
30天前
|
Java 调度
【多线程面试题 五】、 介绍一下线程的生命周期
线程的生命周期包括新建、就绪、运行、阻塞和死亡状态,线程状态会根据线程的执行情况在这些状态之间转换。
【多线程面试题 五】、 介绍一下线程的生命周期
|
1月前
|
Java
多线程线程同步
多线程的锁有几种方式