乐趣区

关于java:突击并发编程JUC系列Locksupport-与-Condition

突击并发编程 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() 办法 返回的状况。包含:

  • 其余线程调用该 Conditionsignal()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 阻塞曾经被放开

欢送关注公众号 山间木匠, 我是小春哥,从事 Java 后端开发,会一点前端、通过继续输入系列技术文章以文会友,如果本文能为您提供帮忙,欢送大家关注、点赞、分享反对,_咱们下期再见!_

退出移动版