使用LockSupport唤醒指定线程
一、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() + "释放许可"); } }