LockSupport与线程中断

简介: LockSupport与线程中断

LockSupport是JDK提供的一种基本的线程同步原语,它可以实现线程的阻塞和唤醒,比synchronized更为灵活,且可以指定唤醒的线程。本文主要介绍LockSupport的用法及其与线程中断的关系。

LockSupport简介

LockSupport是由Doug Lea等人在Java 1.6中引入的一种线程同步工具,它可以阻塞和唤醒线程,并且不需要使用任何锁。它是Java中最基本的线程同步原语之一,也是实现Lock和其他锁的基础。LockSupport通过让线程等待许可证而阻塞线程,许可证可以被其他线程释放。如果许可证在没有发放给线程的情况下被请求,那么该线程将一直阻塞。

LockSupport的API包括以下方法:

public static void park();
public static void park(Object blocker);
public static void unpark(Thread thread);

park()方法用于阻塞当前线程,直到unpark()被调用或中断事件发生。如果线程在调用park()之前被中断,那么它会立即返回。

park(Object blocker)方法可以阻塞当前线程,并将阻塞对象blocker传递给LockSupport,以便于诊断和调试。

unpark(Thread thread)方法则可以唤醒特定的线程,如果线程在调用unpark()之前已经被阻塞,那么它会立即返回。

LockSupport使用示例

下面是一个简单的示例,演示了如何使用LockSupport对线程进行阻塞和唤醒:

public class LockSupportDemo {
    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(() -> {
            System.out.println("线程1开始执行");
            // 调用park()方法阻塞线程1
            LockSupport.park();
            System.out.println("线程1被唤醒");
        });
        t1.start();
        Thread.sleep(2000);
        Thread t2 = new Thread(() -> {
            System.out.println("线程2开始执行");
            // 唤醒线程1
            LockSupport.unpark(t1);
        });
        t2.start();
    }
}

在这个示例中,我们创建了两个线程t1和t2,其中t1会在执行到LockSupport.park()时被阻塞,直到t2调用LockSupport.unpark(t1)唤醒t1,t1才会继续执行。

LockSupport与线程中断

在Java中,线程中断是一种常用的线程协作机制,它可以在任何时候打断一个正在运行的线程,通过抛出InterruptedException异常来通知该线程被中断了。对于被阻塞的线程,如果它正在等待一个锁或者调用了Thread.sleep()等方法,那么它会立即被中断并抛出InterruptedException异常。但是对于正在执行CPU密集型任务的线程,中断信号并不能立即被响应,可能需要等待一段时间才能被响应。

LockSupport与线程中断的关系在于,如果一个线程在调用park()方法阻塞之前被中断,那么会立即返回,不会发生阻塞。而如果一个线程在调用park()方法阻塞之后被中断,那么它需要检查中断标志位并自行处理中断事件。

我们可以通过Thread.interrupted()方法来检查当前线程是否被中断,如果被中断,则需要处理中断事件。下面是一个示例:

public class LockSupportInterruptDemo {
    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(() -> {
            System.out.println("线程1开始执行");
            // 调用park()方法阻塞线程1
            LockSupport.park();
            System.out.println("线程1被唤醒");
            if (Thread.interrupted()) {
                // 处理中断事件
                System.out.println("线程1被中断了");
            }
        });
        t1.start();
        Thread.sleep(2000);
        Thread t2 = new Thread(() -> {
            System.out.println("线程2开始执行");
            // 中断线程1
            t1.interrupt();
            // 唤醒线程1
            LockSupport.unpark(t1);
        });
        t2.start();
    }
}

在这个示例中,我们在t2中断t1之后,调用了LockSupport.unpark(t1)方法唤醒了t1,同时在t1被唤醒之后,使用Thread.interrupted()方法检查当前线程是否被中断,如果被中断,则处理中断事件。

需要注意的是,如果在调用park()方法时已经被中断,那么LockSupport.park()方法不会阻塞,会立即返回。因此,在检查中断标志位之前,需要先调用Thread.interrupted()方法来清除中断标志位,否则后面的代码可能会误判当前线程是否被中断。

总结

LockSupport是Java中最基本的线程同步原语之一,它可以实现线程的阻塞和唤醒,比synchronized更为灵活。LockSupport与线程中断的关系在于,如果一个线程在调用park()方法阻塞之前被中断,那么会立即返回,不会发生阻塞。而如果一个线程在调用park()方法阻塞之后被中断,那么它需要检查中断标志位并自行处理中断事件。在使用LockSupport时需要注意检查中断标志位,以及清除中断标志位。


相关文章
|
9月前
|
Java 测试技术
CountDownLatch、CyclicBarrier让线程听我号令
CountDownLatch、CyclicBarrier让线程听我号令
88 0
|
7月前
|
安全 Java
使用notifyAll唤醒所有等待线程
使用notifyAll唤醒所有等待线程
|
8月前
|
API
java-多线程-CountDownLatch(闭锁) CyclicBarrier(栅栏) Semaphore(信号量)-
java-多线程-CountDownLatch(闭锁) CyclicBarrier(栅栏) Semaphore(信号量)-
52 1
|
8月前
|
Java
使用notifyAll唤醒所有等待线程的方法与比较
使用notifyAll唤醒所有等待线程的方法与比较
|
9月前
|
存储 Java 数据库连接
线程通信(CountDownLatch、CyclicBarrier、Semaphore、Exchanger)
线程通信(CountDownLatch、CyclicBarrier、Semaphore、Exchanger)
90 0
|
9月前
|
Java 索引
多线程并发之CyclicBarrier(栅栏)使用详解
多线程并发之CyclicBarrier(栅栏)使用详解
212 2
|
Java 开发者
停止线程 & 守护线程 & 线程阻塞
停止线程 & 守护线程 & 线程阻塞
36 0
停止线程 & 守护线程 & 线程阻塞
|
Java API
【JUC基础】09. LockSupport
LockSupport是一个线程阻塞工具,可以在线程任意位置让线程阻塞。线程操作阻塞的方式其实还有Thread.suspend()和Object.wait()。而LockSupport与suspend()相比,弥补了由于resume()方法而导致线程被挂起(类似死锁)的问题,也弥补了wait()需要先获得某个对象锁的问题,也不会抛出InterruptedException异常。
|
Java
线程中断方法interrupt、isInterrupted、interrupted方法
线程中断方法interrupt、isInterrupted、interrupted方法
136 0
线程中断方法interrupt、isInterrupted、interrupted方法