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 {@Overridepublic 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 interruptedat 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