线程阻塞之 park() 与 unpark()

115 阅读1分钟

park() 阻塞一个线程

  • 在线程内调用 LockSupport.park() 会暂停当前线程;若是在 park() 之前就调用了 LockSupport.unpark(threadName) ,那么线程在遇到 park() 时,将不会被阻塞。如:
public static void main(String[] args) {
    Thread newThread = new Thread(() -> {
        LockSupport.unpark(Thread.currentThread()); // 提前为当前线程服用解药
        try {
            Thread.sleep(1000);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        LockSupport.park(); // 当前不会中毒阻塞在这里
        System.out.println("no park....");
    });
    newThread.start();
   
}

输出结果:

image.png

unpark(thread) 唤醒一个线程

  • unpark(thread) 一般用于精准地唤醒指定的线程,以达到准确控制线程的执行顺序。如
public static void main(String[] args) {
    Thread newThread = new Thread(() -> {

        try {
            Thread.sleep(1000);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        System.out.println("park....");
        LockSupport.park(); // 阻塞当前线程
        System.out.println("unpark.....");

    });
    newThread.start();
    try {
        Thread.sleep(3000);
        System.out.println("main unpark newThread");
        LockSupport.unpark(newThread); // 为指定的线程解除阻塞
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

执行结果如下:

image.png

park()/unpark() 与 wait/notify/notifyAll 进行对比

  • park 能让当前线程进入阻塞状态,wait 也可以让当前线程进入阻塞状态;
  • park 不会释放锁资源,而 wait 会释放锁资源;
  • park 可以先调用 unpark 避免自身进入阻塞状态,而 wait 不能先调用 notify/notifyAll 避免自身进入阻塞状态;
  • unpark 能准确地让指定的线程从阻塞状态中醒过来,而 notify 只能从等待的线程中随机唤醒一个。