主要介绍LockSupport的park
和unpark
方法
1. 方法展示
代码语言:javascript复制public class LockSupport {
private LockSupport();
private static void setBlocker(Thread t, Object arg);
public static void unpark(Thread thread);
public static void park(Object blocker);
public static void parkNanos(Object blocker, long nanos);
public static void parkUntil(Object blocker, long deadline);
public static Object getBlocker(Thread t);
public static void park();
public static void parkNanos(long nanos);
public static void parkUntil(long deadline);
static final int nextSecondarySeed();
}
2. 方法说明
-
park
表示当前线程阻塞,等待唤醒,相当于Object的wait方法 -
unpark
表示唤醒线程,相当于Object的notify/notifyAll方法
与Object类的wait/notify机制相比,park/unpark有两个优点: 1)以thread为操作对象更符合阻塞线程的直观定义 2)操作更精准,可以准确地唤醒某一个线程(notify随机唤醒一个线程,notifyAll唤醒所有等待的线程),增加了灵活性。 3)park/unpark不用持有锁,将锁和通知模型分离,逻辑更清晰。
另外注意:
- 可以先执行
unpark
,再执行park
操作,类似于生产/消费模型。(参考源码中注释 permit 许可含义) - 多次
unpark
不能叠加,多次unpark
只需一次park
即可抵消掉。
3. 源码分析
LockSupport底层使用UNSAFE
类进行操作,UNSAFE
类均是使用native方法。
public class LockSupport {
...
public static void unpark(Thread thread) {
if (thread != null)
UNSAFE.unpark(thread);
}
public static void park() {
UNSAFE.park(false, 0L);
}
...
}
4. 使用样例
代码语言:javascript复制public class LockSupportTest {
private static Thread thread = new Thread(new MThread());
public static void main(String[] args) throws InterruptedException {
thread.start();
LockSupport.unpark(thread);
LockSupport.unpark(thread);
LockSupport.unpark(thread);
}
public static class MThread implements Runnable{
@Override
public void run() {
try {
Thread.sleep(1000);
LockSupport.park();
System.out.println("Thread unpark 1");
LockSupport.park();
System.out.println("Thread unpark 2");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
- 输出
out => Thread unpark 1