Java~多线程ReentrantLock类常用的十四个方法, 使用Condition实现多线程的顺序执行

方法getHoldCount()

  • 该方法的作用是查询当前被这个锁锁定的线程个数, 也就是这个锁执行lock的次数
public class Demo1 {

    public static void main(String[] args) {
        ReentrantLock reentrantLock = new ReentrantLock();
        Thread thread = new Thread() {
            @Override
            public void run() {
                method1();
            }

            public void method1() {
                reentrantLock.lock();
                System.out.println(Thread.currentThread().getName() + " " +
                        reentrantLock.getHoldCount());
                method2();
                reentrantLock.unlock();
            }

            public void method2() {
                reentrantLock.lock();
                System.out.println(Thread.currentThread().getName() + " " +
                        reentrantLock.getHoldCount());
                reentrantLock.unlock();
            }
        };
        thread.start();
    }
}

在这里插入图片描述

方法getQueueLength()

  • 该方法返回的是想要获取这个锁的线程个数
  • 比如有5个线程,1个线程首先执行await()方法,那么在调用getQueueLength()方法后返回值是4,说明有4个线程同时在等待lock 的释放。
public class Demo2 {

    public static void main(String[] args) throws InterruptedException {
        ReentrantLock reentrantLock = new ReentrantLock();
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                reentrantLock.lock();
                try {
                    Thread.sleep(Integer.MAX_VALUE);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    reentrantLock.unlock();
                }
            }
        };
        Thread[] threads = new Thread[5];
        for (int i = 0; i < 5; i++) {
            threads[i] = new Thread(runnable);
        }
        for (int i = 0; i < 5; i++) {
            threads[i].start();
        }
        Thread.sleep(100);
        System.out.println(reentrantLock.getQueueLength());
    }
}

在这里插入图片描述

方法getWaitQueueLength()

  • 方法int getWaitfQueueI engh(Condition condition)的作用是返回等待与此锁定相关的给定条件Condition的线程估计数,比如有5个线程,每个线程都执行了同一个condition对象的await()方法,则调用getWaitQueueLengh(Condition condition)方法时返回的int值是5。
  • 也就是同一个condition执行await的次数, 也就是目前有多少个线程处于某一个condition的await下
public class Demo3 {

    public static void main(String[] args) {
        ReentrantLock reentrantLock = new ReentrantLock();
        Condition condition = reentrantLock.newCondition();
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                reentrantLock.lock();
                try {
                    System.out.println(reentrantLock.getWaitQueueLength(condition));
                    condition.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        };
        Thread[] threads = new Thread[5];
        for (int i = 0; i < 5; i++) {
            threads[i] = new Thread(runnable);
        }
        for (int i = 0; i < 5; i++) {
            threads[i].start();
        }

    }
}

在这里插入图片描述

方法hasQueuedThread()和方法hasQueuedThreads()

  • 方法boolean hasQueuedThread(Thread thread) 的作用是查询指定的线程是否正在等待获取此锁定。 也就是查看指定线程想要获取锁.
  • 方法boolean hasQueuedThreads()的作用是查询是否有线程正在等待获取此锁定。也就是这个不指定了, 而是只要有想要这把锁的就返回true
public class Demo4 {

    public static void main(String[] args) throws InterruptedException {
        ReentrantLock reentrantLock = new ReentrantLock();
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                reentrantLock.lock();
                try {
                    Thread.sleep(Integer.MAX_VALUE);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    reentrantLock.unlock();
                }
            }
        };
        Thread a = new Thread(runnable);
        a.start();
        Thread.sleep(100);
        Thread b = new Thread(runnable);
        b.start();
        Thread.sleep(100);
        System.out.println("a需要吗? " + reentrantLock.hasQueuedThread(a));
        System.out.println("b需要吗? " + reentrantLock.hasQueuedThread(b));
        System.out.println("有需要吗? " + reentrantLock.hasQueuedThreads());
    }
}

在这里插入图片描述

方法hasWaiters()

  • 方法boolean hasWaiters(Condition condition)的作用是查询是否有线程正在等待与此锁定有关的condition条件。
  • 也就是在这个condition下有没有线程执行了await还没有唤醒
  • 这个方法必须在加锁的情况下使用不然没有对象监视器的所有权, 从而抛出IllegalMonitorStateException
public class Demo5 {

    public static void main(String[] args) throws InterruptedException {
        ReentrantLock reentrantLock = new ReentrantLock();
        Condition condition = reentrantLock.newCondition();
        Thread thread = new Thread() {
            @Override
            public void run() {
                reentrantLock.lock();
                try {
                    condition.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    reentrantLock.unlock();
                }
            }
        };

        thread.start();
        Thread.sleep(100);
        //注意使用这个方法必须在lock下使用, 不然会没有这个对象监视器的所有权而抛出异常
        reentrantLock.lock();
        System.out.println("有没有等待signal的线程 " + reentrantLock.hasWaiters(condition));
        reentrantLock.unlock();
    }
}

在这里插入图片描述

方法isFair()

  • 方法boolean isFair()的作用是判断是不是公平锁。 这个很简单 就不做演示了

方法isHeldByCurrentThread()

  • 方法boolean isHeldByCurrentThread()的作用是查询当前线程是否保持此锁定。
  • 也就是这个线程是否执行了lock
public class Demo6 {

    public static void main(String[] args) {
        ReentrantLock reentrantLock = new ReentrantLock();
        System.out.println(reentrantLock.isHeldByCurrentThread());
        reentrantLock.lock();
        System.out.println(reentrantLock.isHeldByCurrentThread());
        reentrantLock.unlock();
    }
}

在这里插入图片描述

方法isLocked()

  • 方法boolean isLocked()的作用是查询此锁定是否由任意线程保持。
  • 也就是这把锁是否已经执行了lock
public class Demo7 {

    public static void main(String[] args) throws InterruptedException {
        ReentrantLock reentrantLock = new ReentrantLock();
        System.out.println(reentrantLock.isLocked());

        Thread thread = new Thread() {
            @Override
            public void run() {
                reentrantLock.lock();
                System.out.println("执行lock");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    System.out.println("释放lock");
                    reentrantLock.unlock();
                }
            }
        };
        thread.start();
        for (int i = 0; i < 10; i++) {
            System.out.println(reentrantLock.isLocked());
            Thread.sleep(200);
        }


    }
}

在这里插入图片描述

方法lockInterruptibly()、tryLock()和tryLock(long timeout,TimeUnit unit)

  • 这三个方法大同小异
  • 方法void locklnterruptibly()的作用是:如果当前线程未被中断,则获取锁定,如果已经被中断则出现异常。 也就是我们在普通使用lock方法加锁时, 如果这个线程被中断了是不会抛出异常的, 而使用locklnterruptibly方法加锁如果这个线程中断了是会抛出异常的
  • 方法boolean tryLock()的作用是,仅在调用时锁定未被另一个线程保持的情况下,才获取该锁定。 本意就是我尝试去获取锁, 如果没人拿我就拿, 如果有人拿我就不要这把锁了
  • 方法boolean tryLock(long timeout, TimeUnit unit)的作用是,如果锁定在给定等待时间内没有被另一个线程保持,且当前线程未被中断,则获取该锁定。 也就是我会支持一段时间去尝试那这个把锁, 在这个时间段里, 我没拿到我就不要了
public class Service1 {

    private ReentrantLock reentrantLock = new ReentrantLock();

    public void method() {
        try {
            if (reentrantLock.tryLock(3, TimeUnit.SECONDS)) {
                System.out.println(Thread.currentThread().getName() + " " +
                        "获取锁的时间:" + System.currentTimeMillis());
                Thread.sleep(10000);
            } else {
                System.out.println(Thread.currentThread().getName() + " 没有获得锁");
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            if (reentrantLock.isHeldByCurrentThread()) {
                reentrantLock.unlock();
            }
        }
    }
}
public class Demo1 {

    public static void main(String[] args) throws InterruptedException {
        Service1 service1 = new Service1();
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName() + " 执行method时间" +
                        System.currentTimeMillis());
                service1.method();
            }
        };
        Thread a = new Thread(runnable, "A");
        a.start();
        Thread b = new Thread(runnable, "B");
        b.start();
    }
}

在这里插入图片描述

方法awaitUninterruptibly()

  • 我没在普通使用await的时候, 如果这个线程中断了, 就会抛出异常, 但是使用awaitUninterruptibly()即使在等待中的线程被打断了, 也不会抛出异常

方法await(time) 和 awaitUntil()

  • 这俩个方法和synchronized的wait(long)和相似, 就是wait等待一段时间, 可以提前唤醒, 也可以等时间到了自动唤醒.
public class Demo2 {

    public static void main(String[] args) throws InterruptedException {
        ReentrantLock reentrantLock = new ReentrantLock();
        Condition condition = reentrantLock.newCondition();

        reentrantLock.lock();
        System.out.println(Thread.currentThread().getName() + " 开始时间:" +
                System.currentTimeMillis());
        condition.await(3, TimeUnit.SECONDS);
        System.out.println(Thread.currentThread().getName() + " 结束时间:" +
                System.currentTimeMillis());
        reentrantLock.unlock();


    }
}

在这里插入图片描述

使用Condition实现多线程的顺序执行

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

/**
 * Created with IntelliJ IDEA.
 * Description: If you don't work hard, you will a loser.
 * User: Listen-Y.
 * Date: 2020-10-10
 * Time: 18:25
 */
public class Run {

    private static ReentrantLock reentrantLock = new ReentrantLock();
    //关键变量
    volatile private static int key = 1;
    //三个condition保证三种线程 挨个运行
    private static Condition conditionA = reentrantLock.newCondition();
    private static Condition conditionB = reentrantLock.newCondition();
    private static Condition conditionC = reentrantLock.newCondition();

    public static void main(String[] args) {
        //实现三个runnable任务
        Runnable runnableA = new Runnable() {
            @Override
            public void run() {
                try {
                    reentrantLock.lock();
                    while (key != 1) {
                        conditionA.await();
                    }
                    for (int i = 0; i < 3; i++) {
                        System.out.println(Thread.currentThread().getName() + " " + i);
                    }
                    key = 2;
                    //唤醒所有B线程
                    conditionB.signalAll();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    reentrantLock.unlock();
                }
            }
        };
        Runnable runnableB = new Runnable() {
            @Override
            public void run() {
                try {
                    reentrantLock.lock();
                    while (key != 2) {
                        conditionB.await();
                    }
                    for (int i = 0; i < 3; i++) {
                        System.out.println(Thread.currentThread().getName() + " " + i);
                    }
                    key = 3;
                    //唤醒所有C线程
                    conditionC.signalAll();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    reentrantLock.unlock();
                }
            }
        };
        Runnable runnableC = new Runnable() {
            @Override
            public void run() {
                try {
                    reentrantLock.lock();
                    while (key != 3) {
                        conditionC.await();
                    }
                    for (int i = 0; i < 3; i++) {
                        System.out.println(Thread.currentThread().getName() + " " + i);
                    }
                    key = 1;
                    //唤醒所有A线程
                    conditionA.signalAll();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    reentrantLock.unlock();
                }
            }
        };

        //创建多个线程
        Thread[] threadsA = new Thread[5];
        Thread[] threadsB = new Thread[5];
        Thread[] threadsC = new Thread[5];
        for (int i = 0; i < 5; i++) {
            threadsA[i] = new Thread(runnableA, "ThreadA");
            threadsB[i] = new Thread(runnableB, "ThreadB");
            threadsC[i] = new Thread(runnableC, "ThreadC");
        }
        //启动所有线程
        for (int i = 0; i < 5; i++) {
            threadsA[i].start();
            threadsB[i].start();
            threadsC[i].start();
        }
    }
}

在这里插入图片描述

  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值