一、wait与notify、notifyAll
开发过程中,对线程阻塞与唤醒我们都知道可以使用object的wait和notify,notifyAll实现。
以上方式的缺点:notify是随机唤醒某个阻塞的线程,notifyAll唤醒所有阻塞线程,不能实现唤醒指定线程。
二、LockSupport
后来了解到LockSupport类,它位于java.util.concurrent.locks,提供了park()与unpark(thread)结合可以实现
操作。
park
阻塞某线程,调用本地方法实现,源码如下:
public static void park() {
unsafe.park(false, 0L);
}
public native void park(boolean var1, long var2);
API解释
park
public static void park(Object blocker)
为了线程调度,在许可可用之前禁用当前线程。
如果许可可用,则使用该许可,并且该调用立即返回;否则,为线程调度禁用当前线程,并在发生以下三种情况之一前,使其处于休眠状态:
其他某个线程调用将当前线程作为目标调用 unpark;或者
其他某个线程中断当前线程;或者
该调用不合逻辑地(即毫无理由地)返回。
此方法不 报告是哪个线程导致该方法返回。调用者应该重新检查最先导致线程暂停的条件。调用者还可以确定返回时该线程的中断状态。
unpark(thread)
唤醒指定线程,调用本地方法实现,源码如下:
public static void unpark(Thread thread) {
if (thread != null)
unsafe.unpark(thread);
}
public native void unpark(Object var1);
API解释
unpark
public static void unpark(Thread thread)
如果给定线程的许可尚不可用,则使其可用。如果线程在 park 上受阻塞,则它将解除其阻塞状态。否则,保证下一次调用 park 不会受阻塞。如果给定线程尚未启动,则无法保证此操作有任何效果。
参数:
thread - 要执行 unpark 操作的线程;该参数为 null 表示此操作没有任何效果。
三、测试代码
public class TestPark {
public static void main(String[] args) {
System.out.println(System.currentTimeMillis() + "TestPark开始测试====");
System.out.println("该线程线程号为:" + Thread.currentThread().getName());
System.out.println(System.currentTimeMillis() + "将该线程实体传入Test中");
new Thread(new TestThread(Thread.currentThread())).start();
System.out.println(System.currentTimeMillis() + "该线程停止====");
LockSupport.park();
System.out.println(System.currentTimeMillis() + "线程恢复======");
}
}
public class TestThread implements Runnable {
private Thread thread;
public TestThread() {
}
public TestThread(Thread thread) {
this.thread = thread;
}
@Override
public void run() {
try {
System.out.println(System.currentTimeMillis() + "等待开始");
Thread.sleep(1000);
System.out.println(System.currentTimeMillis() + "等待结束");
} catch (Exception e) {
System.out.println("等待失败");
}
LockSupport.unpark(thread);
System.out.println("thread:" + thread.getId() + "释放许可");
}
}