ReentrantLock实现公平锁,可中断,条件变量,可重入案例

1.ReentrantLock实现公平锁

/**
 * ReentrantLock实现公平锁
 * 创建了三个线程,依次打印线程
 */
public class FairLockExample {
    private static ReentrantLock fairLock = new ReentrantLock(true); // 创建公平锁

    public static void main(String[] args) {
        Runnable fairTask = new FairTask();

        // 创建多个线程来竞争公平锁
        Thread thread1 = new Thread(fairTask, "Thread-1");
        Thread thread2 = new Thread(fairTask, "Thread-2");
        Thread thread3 = new Thread(fairTask, "Thread-3");

        thread1.start();
        thread2.start();
        thread3.start();
    }

    static class FairTask implements Runnable {
        @Override
        public void run() {
            while (true) {
                try {
                    fairLock.lock();
                    System.out.println(Thread.currentThread().getName() + " 获取到锁");
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    fairLock.unlock();
                    System.out.println(Thread.currentThread().getName() + " 释放锁");
                }
            }
        }
    }
}

输出结果

Thread-1 获取到锁
Thread-1 释放锁
Thread-2 获取到锁
Thread-2 释放锁
Thread-3 获取到锁
Thread-3 释放锁
Thread-1 获取到锁
Thread-1 释放锁
Thread-2 获取到锁
Thread-2 释放锁
Thread-3 获取到锁
Thread-3 释放锁
Thread-1 获取到锁
Thread-1 释放锁
Thread-2 获取到锁
Thread-2 释放锁
Thread-3 获取到锁

2.ReentrantLock实现可中断锁

/**
 * 演示ReentrantLock调用lockInterruptibly方法可以被中断
 * https://blog.csdn.net/ZSA222/article/details/123433746?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522170022637516800182740333%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=170022637516800182740333&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~top_positive~default-1-123433746-null-null.142^v96^pc_search_result_base5&utm_term=ReentrantLock&spm=1018.2226.3001.4187
 */
public class ReentrantLockInterrupt {
    private static ReentrantLock lock = new ReentrantLock();

    public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread(() -> {
            try {
                // 如果没有竞争那么此方法就会获取 lock 对象锁
                // 如果有竞争就进入阻塞队列,可以被其它线程用 interruput 方法打断
                System.out.println(Thread.currentThread().getName() +  LocalDateTime.now() + "尝试获得锁");
                Thread.sleep(15000);
                lock.lockInterruptibly();
            } catch (InterruptedException e) {
                e.printStackTrace();
                System.out.println(Thread.currentThread().getName() + LocalDateTime.now() + "t1线程没有获得锁,被打断...return");
                return;
            }
            try {
                System.out.println(Thread.currentThread().getName() + LocalDateTime.now() + "t1线程获得了锁");
            } finally {
                lock.unlock();
            }
        }, "t1");

        // t1启动前 主线程先获得了锁
        lock.lock();
        thread.start(); // thread线程会进入阻塞队列
        Thread.sleep(5000);
        System.out.println(Thread.currentThread().getName() + LocalDateTime.now() + "interrupt...打断t1");
        Thread.sleep(2000);
        thread.interrupt();
    }
}

输出结果

t111:27:23尝试获得锁
main11:27:28interrupt...打断t1
java.lang.InterruptedException: sleep interrupted
	at java.lang.Thread.sleep(Native Method)
	at concurrentpro.lock.ReentrantLockInterrupt.lambda$main$0(ReentrantLockInterrupt.java:20)
	at java.lang.Thread.run(Thread.java:750)
t111:27:30t1线程没有获得锁,被打断...return
/**
 * 演示ReentrantLock调用普通lock方法,不能被中断
 * https://blog.csdn.net/ZSA222/article/details/123433746?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522170022637516800182740333%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=170022637516800182740333&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~top_positive~default-1-123433746-null-null.142^v96^pc_search_result_base5&utm_term=ReentrantLock&spm=1018.2226.3001.4187
 */
public class ReentrantLock {
    private static java.util.concurrent.locks.ReentrantLock lock = new java.util.concurrent.locks.ReentrantLock();

    public static void main(String[] args) throws InterruptedException {

        Thread thread = new Thread(() -> {
            System.out.println(LocalDateTime.now().format(DateTimeFormatter.ofPattern("hh:mm:ss")) + Thread.currentThread().getName() + "尝试获得锁");
            lock.lock();
            try {
                System.out.println(LocalDateTime.now().format(DateTimeFormatter.ofPattern("hh:mm:ss")) + Thread.currentThread().getName() + "t1线程获得了锁");
            } finally {
                lock.unlock();
            }
        }, "t1");

        // t1启动前 主线程先获得了锁
        lock.lock();
        thread.start();
        Thread.sleep(1000);
        System.out.println(LocalDateTime.now().format(DateTimeFormatter.ofPattern("hh:mm:ss")) + Thread.currentThread().getName() + "interrupt...打断t1");
        thread.interrupt();
    }
}

输出结果 

11:24:39t1尝试获得锁
11:24:40maininterrupt...打断t1

3.ReentrantLock实现条件变量


/**
 * ReentrantLock 之 condtion的用法
 * 配合 condition.await 和 condition.signal
 * 来源:bilibli 黑马程序员之并发编程
 */
public class ConditionVariable {
    private static boolean hasCigarette = false;
    private static boolean hasTakeout = false;
    private static final ReentrantLock lock = new ReentrantLock();

    // 等待烟的休息室(条件变量)
    static Condition waitCigaretteSet = lock.newCondition();
    // 等外卖的休息室(条件变量)
    static Condition waitTakeoutSet = lock.newCondition();

    public static void main(String[] args) throws InterruptedException {

        new Thread(() -> {
            lock.lock();
            try {
                System.out.println(LocalTime.now() +  Thread.currentThread().getName() + "有烟没?[{}]" + hasCigarette);
                while (!hasCigarette) {
                    System.out.println(LocalTime.now() +   Thread.currentThread().getName()  +"没烟,先歇会!");
                    try {
                        // 此时小南进入到 等烟的休息室
                        waitCigaretteSet.await();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                System.out.println(LocalTime.now() +  Thread.currentThread().getName()  + "烟来咯, 可以开始干活了");
            } finally {
                lock.unlock();
            }
        }, "小南").start();

        new Thread(() -> {
            lock.lock();
            try {
                System.out.println(LocalTime.now() +  Thread.currentThread().getName()  +"外卖送到没?[{}]" + hasTakeout);
                while (!hasTakeout) {
                    System.out.println(LocalTime.now() +  Thread.currentThread().getName()  + "没外卖,先歇会!");
                    try {
                        // 此时小女进入到 等外卖的休息室
                        waitTakeoutSet.await();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                System.out.println(LocalTime.now() +   Thread.currentThread().getName()  +"外卖来咯, 可以开始干活了");
            } finally {
                lock.unlock();
            }
        }, "小女").start();

        Thread.sleep(1000);
        new Thread(() -> {
            lock.lock();
            try {
                System.out.println(LocalTime.now() +  Thread.currentThread().getName()  + "送外卖的来咯~");
                hasTakeout = true;
                // 唤醒等外卖的小女线程
                waitTakeoutSet.signal();
            } finally {
                lock.unlock();
            }
        }, "送外卖的").start();

        Thread.sleep(1000);
        new Thread(() -> {
            lock.lock();
            try {
                System.out.println(LocalTime.now() +  Thread.currentThread().getName()  +"送烟的来咯~");
                hasCigarette = true;
                // 唤醒等烟的小南线程
                waitCigaretteSet.signal();
            } finally {
                lock.unlock();
            }
        }, "送烟的").start();
    }
}

输出结果

11:29:38.644小南有烟没?[{}]false
11:29:38.645小南没烟,先歇会!
11:29:38.645小女外卖送到没?[{}]false
11:29:38.645小女没外卖,先歇会!
11:29:39.620送外卖的送外卖的来咯~
11:29:39.620小女外卖来咯, 可以开始干活了
11:29:40.621送烟的送烟的来咯~
11:29:40.621小南烟来咯, 可以开始干活了

4.ReentrantLock实现可重入

public class ReentrantLockExample {
    private ReentrantLock lock = new ReentrantLock();

    public void performTask() {
        lock.lock();
        try {
            System.out.println("Task started");
            // 可以多次获取锁
            lock.lock();
            try {
                System.out.println("Task is performing");
            } finally {
                lock.unlock();
                System.out.println("Inner lock released");
            }
            System.out.println("Task completed");
        } finally {
            lock.unlock();
            System.out.println("Outer lock released");
        }
    }

    public static void main(String[] args) {
        ReentrantLockExample example = new ReentrantLockExample();
        example.performTask();
    }
}

输出结果

Task started
Task is performing
Inner lock released
Task completed
Outer lock released

猜你喜欢

转载自blog.csdn.net/xuan__xia/article/details/134475948