当前位置: 首页 > 后端技术 > Java

JavaJUCLockSupport概述

时间:2023-04-01 23:00:37 Java

LockSupport工具类LockSupport是rt.jar包中的一个工具类,其主要功能是挂起和唤醒线程,该类是创建锁和其他同步类的基础。LockSupport类和使用它的每个线程都将与一个许可证相关联。默认情况下,调用LockSupport类的方法不持有许可证。LockSupport是使用Unsafe类实现的。下面介绍LockSupport中的主要方法。voidpark()如果在调用park()方法之前已经获得了关联的license,则调用后立即返回,否则禁止参与线程调度,即阻塞挂起。下面的代码最后只会输出“start”,然后会挂起当前线程,因为调用线程默认不持有license。publicstaticvoidmain(String[]args)throwsException{System.out.println("Start...");LockSupport.park();System.out.println("End...");}//结果://Start...当其他线程以当前阻塞的线程为参数调用unpark(Thread线程)方法时,阻塞的线程通过调用park()方法将被返回。当其他线程调用被阻塞线程的interrupt()方法、设置中断标志或线程被误唤醒时,阻塞线程也会被返回。需要注意的是,当调用park()方法的阻塞线程被其他线程中断返回时,不会抛出InterruptedException。许可证是一次性的。比如线程B连续调用了3次unpark()方法。当线程A调用park()方法时,license就用完了。如果线程A再次调用park()方法,则进入等待状态。voidunpark(Threadt)线程调用unpark()方法时,如果传入参数thread不持有permit,则让传入线程持有permit;如果之前调用park()后线程被挂起,线程会在调用unpark()时被唤醒;如果线程之前没有调用过park(),那么在调用unpark()方法后再调用park()方法后会立即返回。publicstaticvoidmain(String[]args)throwsException{System.out.println("Start...");LockSupport.unpark(Thread.currentThread());LockSupport.park();System.out.println("End...");}//输出结果://Start...//End...看下面代码加深对park和unpark的理解。publicstaticvoidmain(String[]args)throwsException{Threadt=newThread(()->{System.out.println("子线程启动...");//自己挂起LockSupport.park();System.out.println("子线程结束...");});t.开始();线程.睡眠(1000);System.out.println("主线程开始调用unpark");锁定支持。unpark(t);}//输出结果://子线程开始...//主线程开始调用unpark//子线程结束...这段代码首先创建了一个子线程t,并在子线程启动后调用park()方法。由于默认情况下子线程不持有许可,因此它会自行挂起。主线程休眠1秒后,调用unpark(),传入子线程t。这是为了让子线程获得license,然后子线程中阻塞的park()就会返回。voidparkNanos(longnanos)类似于park()方法,如果已经获得许可,调用该方法后会立即返回。不同的是,如果没有获得license,调用线程会被挂起nanos时间,然后自动返回。此外,park()方法还支持带有blocker参数的方法voidpark(Objectblocker)方法。当线程未经授权调用park()方法被阻塞挂起时,blocker对象会被记录下来。进入线程。一般用于识别阻塞对象,主要用于故障排除和系统监控。voidparkNanos(Objectblocker,longnanos)与前面的方法相比,该方法增加了超时时间。voidparkUntil(对象拦截器,长期限)publicstaticvoidparkUntil(对象拦截器,长期限){Threadt=Thread.currentThread();setBlocker(t,拦截器);UNSAFE.park(真,截止日期);setBlocker(t,null);}参数deadline的时间单位是ms。这个方法和parkNanos(Objectblocker,longnanos)的区别是后者从当前时间开始等待nanos秒,而前者指定一个时间点,比如2022-01-1912:00:00。总结与Object类的wait/notify机制相比,park/unpark有两个优点:以线程为操作对象更符合阻塞线程的直观定义,操作更精准,可以准确唤醒某个线程(notify随机唤醒一个线程,notifyAll唤醒所有等待的线程),增加灵活性