java中ReentrantLock类如何使用

发布时间:2020-10-10 18:38:51 作者:小新
来源:亿速云 阅读:134

这篇文章主要介绍java中ReentrantLock类如何使用,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!

在 Java 多线程中, 可以使用 synchronized 关键字来实现多线程之间同步互斥, 但在 JDK 1.5 中新增加了 ReentrantLock 类也能达到同样的效果, 并且在扩展功能上也更加强大, 比如具有嗅探锁定, 多路分支通知, 公平锁和非公平锁等(默认)功能, 而且在使用上也比 synchronized 更加的灵活.

使用 ReentrantLock 实现同步

public class MyService {
    private Lock lock = new ReentrantLock();
    public void testMethod() {
        lock.lock();
        for (int i = 0; i < 10; i++){
            System.out.println("ThreadName=" + Thread.currentThread().getName() + (" " + (i + 1)));
        }
        lock.unlock();
    }
}
public class MyThread extends Thread {
    private MyService myService;
    public MyThread(MyService myService) {
        this.myService = myService;
    }
    @Override
    public void run() {
        myService.testMethod();
    }
}
public static void main(String[] args) throws IOException, InterruptedException {
MyService myService = new MyService();
MyThread myThreadA = new MyThread(myService);
        MyThread myThreadB = new MyThread(myService);
        MyThread myThreadC = new MyThread(myService);
        MyThread myThreadD = new MyThread(myService);
        MyThread myThreadE = new MyThread(myService);

        myThreadA.start();
        myThreadB.start();
        myThreadC.start();
        myThreadD.start();
        myThreadE.start();

    }

调用 ReentrantLock 对象的 lock() 方法获取锁, 调用 unLock() 方法释放锁.

从运行结果来看, 当前线程打印完毕之后将锁进行释放, 其他的线程才可以继续打印. 线程打印的数据是分组打印, 因为当前线程已经持有锁, 但线程之间打印的顺序是随机的.

使用 Condition 实现等待/通知

关键字 synchronized 与 wait() 和 notify() / notifyall() 方法结合可以实现等待/通知模式, 只不过在使用时, 调用 notify() 方法 JVM 会随机选择一个 WAITNG 状态的线程来执行.

而使用 Condition 则可以更加灵活, 可以实现 "选择性通知", 可以指定的选择唤醒哪些线程, 哪些线程继续等待.

public class MyService {

    private Lock lock = new ReentrantLock();
    public Condition conditionA = lock.newCondition();
    public Condition conditionB = lock.newCondition();

    public void awaitA() throws InterruptedException {
        lock.lock();

        System.out.println("begin awaitA 时间" + System.currentTimeMillis() + "ThreadName=" + Thread.currentThread().getName());

        conditionA.await();

        System.out.println("end awaitA 时间" + System.currentTimeMillis() + "ThreadName=" + Thread.currentThread().getName());

        lock.unlock();
    }

    public void awaitB() throws InterruptedException {
        lock.lock();

        System.out.println("begin awaitB 时间" + System.currentTimeMillis() + "ThreadName=" + Thread.currentThread().getName());

        conditionB.await();

        System.out.println("end awaitB 时间" + System.currentTimeMillis() + "ThreadName=" + Thread.currentThread().getName());

        lock.unlock();
    }

    public void  signalAll_A() throws InterruptedException {
        lock.lock();
        System.out.println("begin signalAll_A 时间" + System.currentTimeMillis() + "ThreadName=" + Thread.currentThread().getName());

        conditionA.signalAll();

        lock.unlock();
    }

    public void  signalAll_B() throws InterruptedException {
        lock.lock();
        System.out.println("begin signalAll_B 时间" + System.currentTimeMillis() + "ThreadName=" + Thread.currentThread().getName());

        conditionB.signalAll();

        lock.unlock();
    }
}
public class ThreadA extends Thread {

    private MyService myService;
    public ThreadA(MyService myService) {
        this.myService = myService;
    }

    @Override
    public void run() {
        try {
            myService.awaitA();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
public class ThreadB extends Thread {

    private MyService myService;

    public ThreadB(MyService myService) {
        this.myService = myService;
    }

    @Override
    public void run() {
        try {
            myService.awaitB();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
    public static void main(String[] args) throws IOException, InterruptedException {

        MyService myService = new MyService();

        ThreadA threadA = new ThreadA(myService);
        threadA.setName("a");
        threadA.start();

        ThreadB threadB = new ThreadB(myService);
        threadB.setName("b");
        threadB.start();

        Thread.sleep(3000);
        myService.signalAll_A();

    }

从执行结果来看, a 和 b 线程被暂停, 当执行 myService.signalAll_A() 方法时, a 线程继续执行, 而 b 线程仍然是等待状态.

常用方法

ReentrantLock 类

int getHoldCount() 查询调用 lock() 方法的次数.

final int getQueueLength() 估计等待锁的线程数. 比如有5个线程, 1个线程首先执行 await() 方法, 那么在调用此方法后返回值是4, 说明有4个线程同时在等待lock的释放.

int getWaitQueueLength(Condition condition) 返回与此锁相关联给定条件等待的线程数的估计. 比如有5个线程, 每个线程都执行了同一个 condition 对象的 await() 方法, 则调用此方法时返回的值是5.

final boolean hasQueuedThreads() 判断是否有线程等待此锁.

final boolean hasQueuedThread(Thread thread) 判断指定线程是否等待获取此锁.

boolean hasWaiters(Condition condition) 判断线程有没有调用 await() 方法.

void lockInterruptibly() throws InterruptedException 获取锁, 除非当前线程为interrupted.

Condition 类

void awaitUninterruptibly() 和 await() 区别就是当调用 interrupt() 方法时不会抛出 InterrputedException 异常.

以上是java中ReentrantLock类如何使用的所有内容,感谢各位的阅读!希望分享的内容对大家有帮助,更多相关知识,欢迎关注亿速云行业资讯频道!

推荐阅读:
  1. java中ReentrantLock的作用是什么
  2. Java中的显示锁ReentrantLock使用与原理详解

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

java ava

上一篇:腾讯云有虚拟主机吗

下一篇:虚拟主机如何安装dz论坛

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》