突击并发编程 JUC 系列演示代码地址:
- https://github.com/mtcarpenter/JavaTutorial
- Locksupport
JDK 中的 rt.jar 包里面的 LockSupport 是个工具类, 当需要阻塞或唤醒一个线程的时候, 都可以使用 LockSupport 工具类来完成相应工作. LockSupport 定义了一组的公共静态方法, 这些方法提供了最基本的线程阻塞和唤醒功能, 而 LockSupport 也成为构建同步组件的基础工具. LockSupport 定义了一组以 park 开头的方法用来阻塞当前线程, 以及 unpark(Thread thread)方法来唤醒一个被阻塞的线程. 下面介绍 LockSupport 中的几个主要函数.
void park(): 阻塞当前线程, 如果调用
unpark(Thread thread)
方法或者当前线程被中断, 才能从 park()方法返回.
void parkNanos(long nanos)
: 阻塞当前线程, 最长不超过 nanos 纳秒, 返回条件在 park() 的基础上增加了超时返回.
void parkUntil(long deadline)
: 阻塞当前线程, 知道 deadline 时间 (从 1970 年开始到 deadline 时间的毫秒数).
void unpark(Thread thread)
: 唤醒处于阻塞状态的线程 thread.
void park(Object blocker)
: 阻塞当前线程, blocker 用来标识当前线程在等待的对象.
parkNanos(Object blocker, long nanos)
: 比
void park(Object blocker)
增加一个超时时间.
parkUntil(Object blocker, long deadline)
: 比
void parkUntil(long deadline)
多一个阻塞当前对象.
Locksupport 案例上手
- public class LockExample4 {
- public static void main(String[] args) throws Exception {
- Thread t1 = new Thread(new Runnable() {
- @Override
- public void run() {
- System.out.println(Thread.currentThread().getName() + "开始阻塞");
- LockSupport.park();
- System.out.println(Thread.currentThread().getName() + "阻塞已经被放开");
- }
- }, "t1");
- t1.start();
- TimeUnit.SECONDS.sleep(3);
- new Thread(new Runnable() {
- @Override
- public void run() {
- System.out.println(Thread.currentThread().getName() + "开始");
- LockSupport.unpark(t1);
- System.out.println(Thread.currentThread().getName() +"阻塞已经被放开");
- }
- }, "t2").start();
- }
- }
运行结果:
t1 开始阻塞
t2 开始
t2 阻塞已经被放开
t1 阻塞已经被放开
Condition
任意一个 Java 对象, 都拥有一组监视器方法 (定义在 java.lang.Object 上), 主要包括 wait(),wait(long timeout),notify() 以及 notifyAll()方法, 这些方法与 synchronized 同步关键字配合, 可以实现等待 / 通知模式.
Condition 接口也提供了类似 Object 的监视器方法, 与 Lock 配合可以实现等待 / 通知模式, 但是这两者在使用方式以及功能特性上还是有差别的.
Condition 方法说明
void await() throws InterruptedException: 当前线程进入等待状态直到被通知 (signal) 或中断, 当前线程将进入运行状态且从 await() 方法 返回的情况. 包括:
其他线程调用该 Condition 的 signal() 或 signalAll() 方法 , 而当前线程被选中唤醒
其他线程 (调用 Interrupt() 方法)中断当前线程
如果当前等待线程从 await() 方法返回, 那么表明该线程已经获取了 Condition 对象所对应的锁
void awaitUninterruptibly()
: 当前线程进入等待状态被通知, 从方法返回名称上可以看出该方法对中断不敏感
long awaitNanos(long nanosTimeout)
: 当前线程进入等待状态直到被通知, 中断或者超时. 返回值表示剩余的时间, 如果在 nanosTimeout 纳秒之前被唤醒, 那么返回值就是 (nanosTimeout - 实际耗时). 如果返回 0 或者负数, 那么可以认定已经超时了
boolean awaitUntil(Date deadline)
: 当前线程进入等待状态知道被通知, 中断或者到某一个时间. 如果没有到指定时间就被通知, 方法返回 true , 否则, 表示到了指定时间, 方法返回 false.
void signal(): 唤醒一个等待在 Condition 上的线程, 该线程从等待方法返回前必须获得与 Condition 相关的锁
void signalAll(): 唤醒所有等待在 Condition 上的线程, 能够从等待方法返回的线程必须获得与 Condition 相关的锁
Condition 案例上手
- public class LockExample5 {
- public static void main(String[] args) throws Exception {
- Lock lock = new ReentrantLock();
- Condition condition = lock.newCondition();
- Thread t1 = new Thread(new Runnable() {
- @Override
- public void run() {
- lock.lock();
- try {
- System.out.println(Thread.currentThread().getName() + "开始阻塞");
- condition.await();
- System.out.println(Thread.currentThread().getName() + "阻塞已经被放开");
- } catch (InterruptedException e) {
- } finally {
- lock.unlock();
- }
- }
- }, "t1");
- t1.start();
- TimeUnit.SECONDS.sleep(3);
- new Thread(new Runnable() {
- @Override
- public void run() {
- lock.lock();
- try {
- System.out.println(Thread.currentThread().getName() + "开始阻塞");
- condition.signalAll();
- System.out.println(Thread.currentThread().getName() + "阻塞已经被放开");
- } finally {
- lock.unlock();
- }
- }
- }, "t2").start();
- }
- }
运行结果:
t1 开始阻塞
t2 开始阻塞
t2 阻塞已经被放开
t1 阻塞已经被放开
来源: http://www.bubuko.com/infodetail-3682990.html