Java多线程-Lock的使用(2)

公平锁与非公平锁

锁Lock分为“公平锁”和“非公平锁”,公平锁表示线程获取锁的顺序是按照线程请求 lock 的顺序来分配的,即谁先来请求 lock,则 lock被释放的时候,谁就先获取到 lock。

而非公平锁就是一种抢占机制,是随机获得锁的,这种方式可能造成某些线程一直拿不到锁,结果也就是不公平的了。

示例:

public class Test {
    public static void main(String[] args) {
        Service service = new Service(true);
        for (int i = 0; i < 10; i++) {
            new Thread(() -> {
                System.out.println("*线程" + Thread.currentThread().getName() + "运行了");
                service.serviceMethod();
            }).start();
        }
    }

    static class Service {
        private Lock lock;

        public Service(boolean isFair) {
            lock = new ReentrantLock(isFair);
        }

        public void serviceMethod() {
            lock.lock();
            try {
                System.out.println("ThreadName = " + Thread.currentThread().getName() + "获得锁定");
            } finally {
                lock.unlock();
            }

        }
    }
}

运行结果如下:

 线程运行的顺序,基本就是线程获得锁的顺序(这里不是绝对的)

ReentrantLock类的常用方法

int getHoldCount()

查询当前线程保持此锁定的个数,也就是调用 lock() 方法的次数

示例:

public class Test {
    public static void main(String[] args) {
        Service service = new Service();
        service.serviceMethod1();
    }

    static class Service {
        private ReentrantLock lock = new ReentrantLock();

        public void serviceMethod1() {
            lock.lock();
            try {
                System.out.println("serviceMethod1 getHoldCount = " + lock.getHoldCount());
                serviceMethod2();
            } finally {
                lock.unlock();
            }

        }

        public void serviceMethod2() {
            lock.lock();
            try {
                System.out.println("serviceMethod2 getHoldCount = " + lock.getHoldCount());
            } finally {
                lock.unlock();
            }

        }
    }
}

运行结果:

int getQueueLength()

返回正在等待获取此锁的线程估计数

int getWatiQueueLength(Condition condition)

返回等待与此锁相关的给定条件 Condition 的线程估计数。

比如有5个线程,每个线程都执行了同一个 condition 对象的 await() 方法,则调用 getWatiQueueLength(Condition condition) 方法时返回的int 值是 5。

boolean hasQueuedThread(Thread thread)

查询制定的线程是否正在等待获取此锁。

boolean hasQueuedThreads()

查询是否有线程正在等待获取此锁定

boolean hasWaiters(Condition condition)

查询是否有线程正在等待与此锁有关的 condition 条件

boolean isHeldByCurrentThread()

查询当前线程是否保持此锁定

boolean isLocked()

查询此锁是否由任意线程保持

void lockInterruptibly()

如果当前线程为被中断,则获取锁定,如果已经被中断,则抛出异常。

boolean tryLock()

仅在调用时锁未被其它线程保持的情况下,才获取该锁定。

boolean tryLock(long timeout, TimeUnit nuit)

如果锁定在给定等待时间内没有被顶一个线程保持,且当前线程未被中断,则获取该锁定

使用 Condition 实现顺序执行

使用 Condition 对象可以对线程执行的业务进行排序规划

public class Test {
    volatile public static int nextPrintWho = 1;

    private static ReentrantLock lock = new ReentrantLock();
    final private static Condition conditionA = lock.newCondition();
    final private static Condition conditionB = lock.newCondition();
    final private static Condition conditionC = lock.newCondition();
    public static void main(String[] args) {
        Runnable runnableA= () -> {
            lock.lock();
            try {
                while (nextPrintWho != 1) {
                    conditionA.await();
                }
                for (int i = 0; i < 3; i++) {
                    System.out.println("ThreadA " + (i + 1));
                }
                nextPrintWho = 2;
                conditionB.signalAll();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        };
        Runnable runnableB= () -> {
            lock.lock();
            try {
                while (nextPrintWho != 2) {
                    conditionB.await();
                }
                for (int i = 0; i < 3; i++) {
                    System.out.println("ThreadA " + (i + 1));
                }
                nextPrintWho = 3;
                conditionC.signalAll();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        };
        Runnable runnableC= () -> {
            lock.lock();
            try {
                while (nextPrintWho != 3) {
                    conditionC.await();
                }
                for (int i = 0; i < 3; i++) {
                    System.out.println("ThreadA " + (i + 1));
                }
                nextPrintWho = 1;
                conditionA.signalAll();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        };
        for (int i = 0; i < 5; i++) {
            new Thread(runnableA).start();
            new Thread(runnableB).start();
            new Thread(runnableC).start();
        }
    }
}

运行结果如图:

猜你喜欢

转载自www.cnblogs.com/lkc9/p/12564910.html