LockSupport
park和unpark
可以实现类似wait和notify
的功能,但是并不和wait和notify
交叉,也就是说unpark
不会对wait
起作用,notify
也不会对park
起作用。
park和unpark
的使用不会出现死锁的情况blocker的作用是在dump线程的时候看到阻塞对象的信息
并且在park 的时候出现中断,也不会抛出异常
Thread thread1 = new Thread(()-> {
System.out.println(Thread.currentThread().getName() + " 进入");
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " 唤醒");
LockSupport.park();
System.out.println(Thread.currentThread().getName() + " 退出");
}, "线程1");
Thread thread2 = new Thread(()-> {
thread1.interrupt();
}, "线程1");
thread2.start();
Thread.sleep(2000);
System.out.println("我现在就要退出");
LockSupport.unpark(thread1);
问题1: 还有一个地方需要注意,相对于线程的
stop和resume
,park和unpark
的先后顺序并不是那么严格。stop和resume
如果顺序反了,会出现死锁现象。而park和unpark
却不会。这又是为什么呢?还是看一个例子(为什么不会出现死锁)
unpark
//提供给定线程的许可证(如果它还没有可用)。
// 1. 如果线程在park上被阻塞,那么它将被解除阻塞。
// 2. 如果还没有调用过 park, 则保证下一次调用park 不会阻塞
// 3. 如果没有启动给定的线程,则不能保证此操作有任何效果。(可能会死锁)
Thread thread1 = new Thread(()-> {
System.out.println(Thread.currentThread().getName() + " 进入");
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " 唤醒");
LockSupport.park();
System.out.println(Thread.currentThread().getName() + " 退出");
}, "线程1");
Thread.sleep(2000);
System.out.println("我现在就要退出");
LockSupport.unpark(thread1);
thread1.start();
// unpark 在线程启动之前, 因此进入死锁
下面的代码就不会进入死锁
Thread thread1 = new Thread(()-> {
System.out.println(Thread.currentThread().getName() + " 进入");
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " 唤醒");
LockSupport.park();
System.out.println(Thread.currentThread().getName() + " 退出");
}, "线程1");
thread1.start();
Thread.sleep(2000);
System.out.println("我现在就要退出");
LockSupport.unpark(thread1);