一、初步认识
LockSupport 是一个灵活的线程工具类,主要是为了阻塞和唤醒线程用的,查看 API 或 源码可知,它的所有方法都是静态方法
// 阻塞当前线程 / 禁止当前线程调度,除非许可证可用
public static void park(Object blocker)
// 暂停当前线程,有超时时间 / 禁用当前线程进行线程调度,直到指定的等待时间,除非许可证可用
public static void parkNanos(Object blocker, long nanos)
// 暂停当前线程,直到某个时间 / 禁用当前线程进行线程调度,直到指定的截止日期,除非许可证可用
public static void parkUntil(Object blocker, long deadline)
// 恢复当前线程/为给定的线程提供许可证(如果尚未提供)
public static void unpark(Thread thread)
// 返回提供给最近尚未解除阻塞的 park 方法的阻止程序对象,如果不阻止则返回 null
public static Object getBlocker(Thread t)
// 无线暂停当前线程 / 禁止当前线程调度,除非许可证可用
public static void park()
// 暂停当前线程,有超时时间限制 / 禁用当前线程进行线程调度,直到指定的等待时间,除非许可证可用
public static void parkNanos(long nanos)
// 暂停当前线程,有超时时间限制 / 禁用当前线程进行线程调度,直到指定的等待时间,除非许可证可用
public static void parkUntil(long deadline)
其中 blocker 是用来记录线程被阻塞时被谁阻塞的,主要用于线程监控和分析工具来定位原因。
简单的使用案例:
public class LockSupportTest {
public static void main(String[] args) throws InterruptedException {
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
System.out.println(“线程启动…”);
LockSupport.park(); // 暂停线程执
System.out.println(“线程被唤醒,继续向下执行…”);
}
});
thread.start(); // 启动线程
//主线程 sleep 1000 毫秒,看控制台打印结果,
//若 主线程的打印 存在在 thread 第二次打印后面,则证明 LockSupport 没起作用
Thread.currentThread().sleep(1000);
System.out.println(“LockSupport 进行了 unpark”);
LockSupport.unpark(thread);
}
}
方法 作用
wait/notify wait/notify 都是 Object 中的方法,在调用这两个方法前必须先获得锁对象 ; notify 只能随机选择一个线程唤醒,无法唤醒指定的线程
park /unpark park /unpark 不需要获取某个对象的锁就可以锁住线程; unpark 可以唤醒一个指定的线程
二、 源码查看
/**
* Makes available the permit for the given thread, if it
* was not already available. If the thread was blocked on
* {@code park} then it will unblock. Otherwise, its next call
* to {@code park} is guaranteed not to block. This operation
* is not guaranteed to have any effect at all if the given
* thread has not been started.
*
* @param thread the thread to unpark, or {@code null}, in which case
* this operation has no effect
*/
/*
* 如果给定线程尚不可用,则使它可用。如果线程在 park 上被阻止,则它将取消阻止
* 以确保对其 park 的下一次调用不会阻塞,如果给定线程尚未启动,则不能办证此操
* 作完全无效
* 参数 thread 要 unpark 的线程,或 null,在这种情况下,此操作无效
*/
public static void unpark(Thread thread) {
if (thread != null)
UNSAFE.unpark(thread);
}
/**
* Disables the current thread for thread scheduling purposes unless the
* permit is available.
*
* <p>If the permit is available then it is consumed and the call returns
* immediately; otherwise
* the current thread becomes disabled for thread scheduling
* purposes and lies dormant until one of three things happens:
*
* <ul>
* <li>Some other thread invokes {@link #unpark unpark} with the
* current thread as the target; or
*
* <li>Some other thread {@linkplain Thread#interrupt interrupts}
* the current thread; or
*
* <li>The call spuriously (that is, for no reason) returns.
* </ul>
*
* <p>This method does <em>not</em> report which of these caused the
* method to return. Callers should re-check the conditions which caused
* the thread to park in the first place. Callers may also determine,
* for example, the interrupt status of the thread upon return.
*
* @param blocker the synchronization object responsible for this
* thread parking
* @since 1.6
*/
/**
* 除非有许可,否则出于线程调度目的禁用当前线程
* 如果许可证可用,则它被消耗掉,并且该调用立即返回;否则当前线程对于线程调度
* 目的将被禁用,并且处于休眠状态,直到发生四件事情之一:
* 一些其它线程以当前线程作为目标调用 unpark 方法
* 一些其它线程打断当前线程
* 经过指定的等待时间
* 虚假地(即无故)调用返回
* 这种方法不报告使哪个线程导致该方法返回,调用者应首先重新检查线程造成线程 park 的条件
* 例如: