廖雪峰Java11多线程编程-3高级concurrent包-3Condition

1.Condition实现等待和唤醒线程

java.util.locks.ReentrantLock用于替代synchronized加锁

但是synchronized可以使用wait和notify实现线程在条件不满足时的等待,条件满足时的唤醒。
如何使用ReentrantLock实现wait/notify的功能?
这个时候我们可以使用Condition对象来实现条件不满足时的等待,条件满足时的唤醒。

class TaskQueue{
    final Lock lock = new ReentrantLock()
    final Condition notEmpty = lock.newCondition();
}

1.1 对Condition对象调用await()方法就相当于对所对象调用wait()方法。

### 1.2 对Condition对象调用signalAll()就相当于在synchronized加锁对象调用notifyAll()方法。 Condition.await/signal/signalAll原理和wait/notify/notifyAll一致 * await()会释放当前锁,进入等待状态 * signal()会唤醒某个等待线程 * signalAll()会唤醒所有等待线程 * 唤醒线程从await()返回后需要重新获得锁

2. 示例

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;

class TaskQueue{
    final Queue<String> queue = new LinkedList<>();
    final Lock lock = new ReentrantLock();
    final Condition notEmpty = lock.newCondition();
    public String getTask() throws InterruptedException{
        lock.lock();
        try{
            while(this.queue.isEmpty()){
                notEmpty.await();
            }
            return queue.remove();
        }finally {
            lock.unlock();
        }
    }
    public void addTask(String name){
        lock.lock();
        try{
            this.queue.add(name);
            notEmpty.signalAll();
        }finally {
            lock.unlock();
        }
    }
}
class WorkerThread extends Thread{
    TaskQueue taskQueue;
    public WorkerThread(TaskQueue taskQueue){
        this.taskQueue = taskQueue;
    }
    public void run(){
        while(!isInterrupted()){
            String name;
            try{
                name = taskQueue.getTask();
            }catch (InterruptedException e){
                break;
            }
            String result = "Hello, "+name+" !";
            System.out.println(result);
        }
    }
}
public class Main{
    public static void main(String[] args) throws InterruptedException{
        TaskQueue taskQueue = new 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");
    }
}
## 3. 总结 使用ReentrantLock+Condition可以更安全的实现线程的同步、等待和唤醒。 * Condition可以替代wait/notify * Condition对象必须从ReentrantLock对象获取 * ReentrantLock+Condition可以替代synchronized+wait/notify
posted on 2019-06-12 22:21  singleSpace  阅读(199)  评论(0编辑  收藏  举报