如何理解并使用 park 与 unpark

简介: park和unpark是Java中的两个线程同步工具,用于线程的阻塞和唤醒操作。

tip: 作为程序员一定学习编程之道,一定要对代码的编写有追求,不能实现就完事了。我们应该让自己写的代码更加优雅,即使这会费时费力。

一、基本介绍

park和unpark是Java中的两个线程同步工具,用于线程的阻塞和唤醒操作。

park方法是线程阻塞的方法,可以使当前线程进入等待状态,直到被其他线程唤醒。park方法有多个重载方法,其中最常用的是park()方法,该方法会使当前线程进入等待状态,直到被其他线程使用unpark方法唤醒。park方法还可以传入一个Object类型的参数,用于标识当前线程等待的条件,当该条件满足时,线程会被唤醒。

unpark方法是线程唤醒的方法,可以唤醒指定的线程。unpark方法也有多个重载方法,其中最常用的是unpark(Thread thread)方法,该方法可以唤醒指定的线程。如果该线程之前调用了park方法进入等待状态,那么它会被唤醒;如果该线程还没有调用park方法,那么它在调用park方法之后会立即返回。

park和unpark方法常用于实现线程的等待和唤醒操作,可以用于各种线程同步场景。需要注意的是,park和unpark方法应该谨慎使用,避免出现死锁等问题。

二、使用例子

package com.pany.camp.lock;

import java.util.concurrent.locks.LockSupport;

public class ParkDemo {
   

    public static void main(String[] args) {
   
        Thread thread1 = new Thread(() -> {
   
            System.out.println("Thread 1 is waiting...");
            LockSupport.park(); // 线程1等待
            System.out.println("Thread 1 is awakened.");
        });

        Thread thread2 = new Thread(() -> {
   
            System.out.println("Thread 2 is waiting...");
            LockSupport.park(); // 线程2等待
            System.out.println("Thread 2 is awakened.");
        });

        thread1.start();
        thread2.start();

        try {
   
            System.out.println("wait 2 s.");
            Thread.sleep(2000); // 等待2秒钟
        } catch (InterruptedException e) {
   
            e.printStackTrace();
        }

        LockSupport.unpark(thread1); // 唤醒线程1
        LockSupport.unpark(thread2); // 唤醒线程2
    }
}

image.png

在上面的代码中,我们创建了两个线程thread1和thread2,它们都调用了LockSupport.park()方法进入等待状态。然后我们等待了2秒钟,之后分别调用了LockSupport.unpark()方法唤醒线程1和线程2。当线程被唤醒时,它们会继续执行后面的代码。

三、使用注意事项

使用park和unpark方法需要注意以下几点:

  1. park和unpark方法应该配对使用,否则可能会出现死锁等问题,因此在使用时应该确保调用unpark方法的次数不超过调用park方法的次数。

  2. park方法可能会在没有调用unpark方法的情况下一直阻塞线程,因此在使用时应该确保线程有被唤醒的机会。

  3. park和unpark方法可以用于线程的等待和唤醒操作,但是在某些情况下可能不是最优的选择,因此在使用时应该根据具体情况选择合适的线程同步机制。

  4. park和unpark方法是比较底层的线程同步工具,使用时需要注意线程安全和可读性等问题,避免出现潜在的问题。

总之,使用park和unpark方法需要谨慎,遵循最佳实践,才能保证线程同步的正确性和高效性。

目录
相关文章
|
存储 API
一种新的方法来存储用户信息——ThreadLocal
一种新的方法来存储用户信息——ThreadLocal
1546 0
|
9月前
|
消息中间件 NoSQL 架构师
招行面试:亿级秒杀,超卖问题+少卖问题,如何解决?(图解+秒懂+史上最全)
45岁资深架构师尼恩在读者交流群中分享了如何系统化解决高并发下的库存抢购超卖少买问题,特别是针对一线互联网企业的面试题。文章详细解析了秒杀系统的四个阶段(扣库预扣、库存扣减、支付回调、库存补偿),并通过Redis分布式锁和Java代码示例展示了如何防止超卖。此外,还介绍了使用RocketMQ延迟消息和xxl-job定时任务解决少卖问题的方法。尼恩强调,掌握这些技术不仅能提升面试表现,还能增强实际项目中的高并发处理能力。相关答案已收入《尼恩Java面试宝典PDF》V175版本,供后续参考。
|
10月前
|
缓存 安全 Java
Java volatile关键字:你真的懂了吗?
`volatile` 是 Java 中的轻量级同步机制,主要用于保证多线程环境下共享变量的可见性和防止指令重排。它确保一个线程对 `volatile` 变量的修改能立即被其他线程看到,但不能保证原子性。典型应用场景包括状态标记、双重检查锁定和安全发布对象等。`volatile` 适用于布尔型、字节型等简单类型及引用类型,不适用于 `long` 和 `double` 类型。与 `synchronized` 不同,`volatile` 不提供互斥性,因此在需要互斥的场景下不能替代 `synchronized`。
3225 3
|
存储 算法 关系型数据库
(二十二)全解MySQL之分库分表后带来的“副作用”一站式解决方案!
上篇《分库分表的正确姿势》中已经将分库分表的方法论全面阐述清楚了,总体看下来用一个字形容,那就是爽!尤其是分库分表技术能够让数据存储层真正成为三高架构,但前面爽是爽了,接着一起来看看分库分表后产生一系列的后患问题,注意我这里的用词,是一系列而不是几个,也就是分库分表虽然好,但你要解决的问题是海量的。
1016 3
|
11月前
|
消息中间件 存储 Kafka
RocketMQ 工作原理图解,看这篇就够了!
本文详细解析了 RocketMQ 的核心架构、消息领域模型、关键特性和应用场景,帮助深入理解消息中间件的工作原理。关注【mikechen的互联网架构】,10年+BAT架构经验倾囊相授。
RocketMQ 工作原理图解,看这篇就够了!
|
Java 应用服务中间件 nginx
一文读懂:Nginx 和Gateway
一文读懂:Nginx 和Gateway
1380 1
|
11月前
|
消息中间件 存储 Java
吃透 RocketMQ 消息中间件,看这篇就够了!
本文详细介绍 RocketMQ 的五大要点、核心特性及应用场景,涵盖高并发业务场景下的消息中间件关键知识点。关注【mikechen的互联网架构】,10年+BAT架构经验倾囊相授。
吃透 RocketMQ 消息中间件,看这篇就够了!
|
11月前
|
消息中间件 存储 缓存
QPS多少,才算高并发 ?
本文详解高并发概念及 QPS 标准,大厂面试高频点,建议掌握收藏。关注【mikechen的互联网架构】,10年+BAT架构经验分享。
QPS多少,才算高并发 ?
|
Java
线程池中线程抛了异常,该如何处理?
【8月更文挑战第27天】在Java多线程编程中,线程池(ThreadPool)是一种常用的并发处理工具,它能够有效地管理线程的生命周期,提高资源利用率,并简化并发编程的复杂性。然而,当线程池中的线程在执行任务时抛出异常,如果不妥善处理,这些异常可能会导致程序出现未预料的行为,甚至崩溃。因此,了解并掌握线程池异常处理机制至关重要。
968 0
|
JSON Java fastjson
JMH - Java 代码性能测试的终极利器、必须掌握
JMH - Java 代码性能测试的终极利器、必须掌握
4342 1