我们已经知道java.util.lock中ReentrantLock可以替代synchronized加锁
但是synchronized可以配合wait()和notify()实现条件不满足的时候等待,条件满足的时候放行
如果使用ReentrantLock怎么实现编写wait和notify的功能呢?
这个时候我们就可以使用condition对象,condition对象就可以实现wait和notify的功能
我们创建condition对象是通过lock.newCondition()方法返回的
Condition.wait/signal/signalAll原理和wait/notify/notifyAll一致
1. await()会释放锁,进入等待状态
2. signal()会唤醒某个等待线程
3. signalAll()会唤醒所有等待线程
4. 唤醒线程从await()返回后需要重新获的锁对象
package com.leon.day05;
import java.util.LinkedList;
import java.util.Queue;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class TaskQueue {
// 首先定义一个LinkedList来作为Queue
final Queue<String> queue = new LinkedList<>();
final Lock lock = new ReentrantLock();
final Condition condition = lock.newCondition();
public String getTask() throws InterruptedException {
lock.lock();
try {
// 我们在getTask()方法中判断是不是empty
while(this.queue.isEmpty()) {
// 如果是的话就进入等待状态
condition.await();
}
return queue.remove();
}finally {
lock.unlock();
}
}
// 在addTask方法中首先获得锁,然后往队列中添加一个任务,紧接着我们对condition对象调用
public synchronized void addTask(String name) {
lock.lock();
try {
// 我们在addTask()中向队列加入一个任务
this.queue.add(name);
// signalAll唤醒正在等待的线程
condition.signalAll();
}finally {
lock.unlock();
}
}
public static void main(String[] args) throws InterruptedException {
// 最后我们通过一个main方法创建一个TaskQueue
TaskQueue taskQueue = new TaskQueue();
// 创建一个WorkerThread,我们往TaskQueue中添加三个任务
WorkerThread worker = new WorkerThread(taskQueue);
worker.start();
taskQueue.addTask("Bob");
Thread.sleep(1000);
taskQueue.addTask("Alice");
Thread.sleep(1000);
taskQueue.addTask("Tim");
Thread.sleep(1000);
worker.interrupt();
worker.join();
System.out.println("END");
}
}
class WorkerThread extends Thread{
TaskQueue taskQueue;
public WorkerThread(TaskQueue taskQueue) {
this.taskQueue = taskQueue;
}
@Override
public void run() {
while(!isInterrupted()) {
String name;
try {
// 不断的从队列中获取任务
// getTask有可能让当前对象进入等待状态
// 当getTask返回的时候我们一定能够拿到一个任务
name = taskQueue.getTask();
} catch (InterruptedException e) {
break;
}
String result = "Hello, " + name + "!";
System.out.println(result);
}
}
}
这个代码的结果和我们使用synchronized和wait和notify是一样的
但是我们使用ReentrantLock和Condition可以更安全的实现线程的同步,等待和唤醒
Condition 可以用来替代 wait/notify
Condition对象必须从ReentrantLock对象中获取
ReentrantLock + Condition可以替代synchronized + wait/notify