LockSupport是jdk自带的线程阻塞、唤醒工具类
此工具类属于juc包的一部分,所在包路径:java.util.concurrent.locks.LockSupport。
LockSupport类使用了一种名为Permit(许可)的概念来做到阻塞和唤醒线程的功能,可以把许可看成是一种(0,1)信号量(Semaphore),但与 Semaphore 不同的是,许可的累加上限是1。
初始时,permit为0,当调用unpark()方法时,线程的permit加1,当调用park()方法时,如果permit为0,则调用线程进入阻塞状态。
使用LockSupport实现线程的阻塞和唤醒
package com.dongguo.sync;
import java.util.concurrent.locks.LockSupport;
/**
* @author Dongguo
* @date 2021/8/24 0024-17:15
* @description: LockSupport示例
*/
public class ThreadDemo5 {
static boolean flag = true;
static Thread threadA;
public static void main(String[] args) {
DemoClass demoClass = new DemoClass();
threadA = new Thread(() -> {
demoClass.increment();
}, "ThreadA");
threadA.start();
new Thread(() -> {
demoClass.decrement();
}, "ThreadB").start();
}
static class DemoClass {
private int number = 0;
//加一
public void increment() {
try {
while (true) {
while (number != 0) {
LockSupport.park();
}
if (flag) {
number++;
System.out.println(Thread.currentThread().getName() + "+1值为:" + number);
flag = false;
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
//减一
public void decrement() {
try {
while (true) {
if (!flag) {
number--;
System.out.println(Thread.currentThread().getName() + "-1值为:" + number);
flag = true;
}
LockSupport.unpark(threadA);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
通过LockSupport的这两个方法,可以很方便的阻塞和唤醒线程。但是LockSupport的使用过程中还需要注意以下几点:
- park方法的调用一般要方法一个循环判断体里面。
- park方法是会响应中断的,但是不会抛出异常。(也就是说如果当前调用线程被中断,则会立即返回但不会抛出中断异常)
- park的重载方法park(Object blocker),会传入一个blocker对象,所谓Blocker对象,其实就是当前线程调用时所在调用对象(如上述示例中的FIFOMutex对象)。该对象一般供监视、诊断工具确定线程受阻塞的原因时使用。