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