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时需要注意检查中断标志位,以及清除中断标志位。