版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/ocp114/article/details/82851890
先讲讲主要的 api
名称 | 描述 |
---|---|
park() | 相当于 suspend() 使线程挂起 |
unpark(Thread thread) | 相当于 thread.resume() 唤醒线程 |
park(Object blocker) | 功能和 park() 一样,但是 blocker 可以当作参数在不同线间传递 |
getBlocker(Thread t) | 可以获取到线程 t 调用 park(Object blocker) 时传进去的 blocker |
parkNanos(long nanos) | nanos 为纳秒,1毫秒(ms) = 1000000纳秒(ns),让当前线程最长沉睡 nanos 时间长度(如果有其他线程在这时间内唤醒的话,会立刻运行) |
parkNanos(Object blocker, long nanos) | 这个就不说了,用大腿想想 |
parkUntil(long deadline) | deadline 为未来的一个时间时间戳,单位是毫秒,方法是作用是让当前线程沉睡至 deadline 的时间后重新唤醒 |
parkUntil(Object blocker, long deadline) | 哈~这个也不说 |
一些特性:
- 全部静态方法,方便调用
- 底层通过 Unsafe 来实现,可以说是有借助系统层级还有硬件相关的放来来实现锁的控制了
- 被阻塞的线程可以被中断,不抛异常,可以通过 isInterrupted() 查询是否被中断,被中断的锁所在的线程会立刻往下执行,有点像调用了 unpark(Thread thread) 方法
- park() 和 unpark(Thread thread) 调用的次序可以掉乱,但是,如果在 park() 前调用了 unpark(Thread thread) 那么这个 park() 方法基本上就是废了
基本使用:
public class TestLockSupport {
private static SimpleDateFormat formatter = new SimpleDateFormat("HH:mm:ss:SSS");
static class TestThread implements Runnable {
@Override
public void run() {
System.out.println("1) " + formatter.format(new Date()) + " : " + Thread.currentThread().getName() + " 进来了");
System.out.println("2) " + formatter.format(new Date()) + " : " + "执行普通 park() 让线程挂起 ");
LockSupport.park();
System.out.println("4) " + formatter.format(new Date()) + " : " + "执行 park(blocker) 为主线程传递参数 ");
String blocker = "我是 blocker";
LockSupport.park(blocker);
System.out.println("7) " + formatter.format(new Date()) + " : " + "执行 parkNanos(nanos) 让线程沉睡 2 秒 ");
LockSupport.parkNanos(2000000000);
String blocker1 = "我是 blocker1";
System.out.println("8) " + formatter.format(new Date()) + " : " + "执行 parkNanos(blocker, nanos) 让线程沉睡 2 秒,并为主线程传递参数");
LockSupport.parkNanos(blocker1, 2000000000);
System.out.println("10) " + formatter.format(new Date()) + " : " + "执行 parkUntil(deadline) 让线程沉睡在未来是一个时间戳醒来");
LockSupport.parkUntil(System.currentTimeMillis() + 2000);
System.out.println("11) " + formatter.format(new Date()) + " : " + "执行 parkUntil(blocker, deadline) 让线程沉睡在未来是一个时间戳醒来,并为主线程传递参数");
String blocker2 = "我是 blocker2";
LockSupport.parkUntil(blocker2, System.currentTimeMillis() + 2000);
System.out.println("13) " + formatter.format(new Date()) + " : " + "定时 10 秒后重新启动,测试锁中断,中断时会立刻往下执行");
LockSupport.parkUntil(System.currentTimeMillis() + 10000);
System.out.println("15) " + formatter.format(new Date()) + " ==== 所有步骤执行完毕 ==== ");
}
}
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(new TestThread(), "线程 1");
t1.start();
Thread.sleep(2000);
System.out.println("3) " + formatter.format(new Date()) + " : " + "执行 unpark(t1) t1 重新运行 ");
LockSupport.unpark(t1);
Thread.sleep(2000);
String blocker = (String) LockSupport.getBlocker(t1);
System.out.println("5) " + formatter.format(new Date()) + " : " + "执行 getBlocker(t1) 从 t1 中获取到 blocker = " + blocker);
System.out.println("6) " + formatter.format(new Date()) + " : " + "执行 unpark(t1) t1 重新运行");
LockSupport.unpark(t1);
Thread.sleep(3000);
String blocker1 = (String) LockSupport.getBlocker(t1);
System.out.println("9) " + formatter.format(new Date()) + " : " + "执行 getBlocker(t1) 从 t1 中获取到 blocker1 = " + blocker1);
Thread.sleep(5000);
String blocker2 = (String) LockSupport.getBlocker(t1);
System.out.println("12) " + formatter.format(new Date()) + " : " + "执行 getBlocker(t1) 从 t1 中获取到 blocker2 = " + blocker2);
Thread.sleep(1000);
System.out.println("14) " + formatter.format(new Date()) + " : " + "开始中断锁");
t1.interrupt();
}
}
输出结果
- 15:11:12:443 : 线程 1 进来了
- 15:11:12:443 : 执行普通 park() 让线程挂起
- 15:11:14:443 : 执行 unpark(t1) t1 重新运行
- 15:11:14:443 : 执行 park(blocker) 为主线程传递参数
- 15:11:16:443 : 执行 getBlocker(t1) 从 t1 中获取到 blocker = 我是 blocker
- 15:11:16:443 : 执行 unpark(t1) t1 重新运行
- 15:11:16:443 : 执行 parkNanos(nanos) 让线程沉睡 2 秒
- 15:11:18:444 : 执行 parkNanos(blocker, nanos) 让线程沉睡 2 秒,并为主线程传递参数
- 15:11:19:444 : 执行 getBlocker(t1) 从 t1 中获取到 blocker1 = 我是 blocker1
- 15:11:20:445 : 执行 parkUntil(deadline) 让线程沉睡在未来是一个时间戳醒来
- 15:11:22:445 : 执行 parkUntil(blocker, deadline) 让线程沉睡在未来是一个时间戳醒来,并为主线程传递参数
- 15:11:24:445 : 执行 getBlocker(t1) 从 t1 中获取到 blocker2 = 我是 blocker2
- 15:11:24:446 : 定时 10 秒后重新启动,测试锁中断,中断时会立刻往下执行
- 15:11:25:445 : 开始中断锁
- 15:11:25:445 : ==== 所有步骤执行完毕 ====