他们是 LockSupport 类的方法。
使用
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| package com.redisc;
import lombok.extern.slf4j.Slf4j;
import java.io.IOException; import java.nio.ByteBuffer; import java.util.concurrent.locks.LockSupport;
@Slf4j(topic = "c.Run") public class Run {
public static void main(String[] args) throws Exception { Thread t1 = new Thread(() -> { log.debug("start..."); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } log.debug("park..."); LockSupport.park(); log.debug("resume"); }); t1.start();
Thread.sleep(2000); log.debug("unpark"); LockSupport.unpark(t1); }
}
|
输出
1 2 3 4
| 18:53:28.860 [Thread-0] DEBUG c.Run - start... 18:53:29.867 [Thread-0] DEBUG c.Run - park... 18:53:30.859 [main] DEBUG c.Run - unpark 18:53:30.859 [Thread-0] DEBUG c.Run - resume
|
unpark
既可以在 park
之前调用,也可以之后调用,上面的代码是之后调用,下面的代码是之前调用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| package com.redisc;
import lombok.extern.slf4j.Slf4j;
import java.io.IOException; import java.nio.ByteBuffer; import java.util.concurrent.locks.LockSupport;
@Slf4j(topic = "c.Run") public class Run {
public static void main(String[] args) throws Exception { Thread t1 = new Thread(() -> { log.debug("start..."); try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } log.debug("park..."); LockSupport.park(); log.debug("resume"); }); t1.start();
Thread.sleep(1000); log.debug("unpark"); LockSupport.unpark(t1); }
}
|
输出
1 2 3 4
| 21:13:35.544 [Thread-0] DEBUG c.Run - start... 21:13:36.534 [main] DEBUG c.Run - unpark 21:13:37.550 [Thread-0] DEBUG c.Run - park... 21:13:37.551 [Thread-0] DEBUG c.Run - resume
|
wait
、notify
、notifyAll
必须配合 Object Monitor
一起使用,而 unpark
不必
park & unpark
是以线程为单位进行「阻塞」和「唤醒」的,而 notify
只能随机唤醒一个等待线程
park & unpark
可以先 unpark
,而 wati & notify
不能先 notify
原理
每个线程都有自己的一个 Parker 对象,由三个部分组成
举一个例子
- 线程就像一个旅人,Parker 就像他随身携带的背包,条件变量就好像是背包中的帐篷。
_counter
就好像背包中的备用干粮「0
为耗尽、1
为充足」
- 调用
park
就是看需不需要停下来休息
- 如果备用干粮耗尽,那么钻进帐篷休息
- 如果备用条件充足,那么,不需要停留,继续前进
- 调用
unpark
,就是补充干粮,让干粮充足
- 如果这时线程在帐篷中,就唤醒让他继续前进
- 如果这时线程还在运行,那么,下次他调用
park
时,仅是消耗备用干粮,不需要停留继续前进
- 因为背包空间有限,多次
unpark
也只会补充一份干粮