基本前提知识:
一:Object/wait(), notify(), notifyAll()
1:wait() 方法暂停当前线程,并立即释放对象锁;
2:notify()/notifyAll() 方法唤醒其他等待该对象锁的线程,并在执行完同步代码块中的后续步骤后,释放对象锁
3:notify()和notifyAll()的区别在于:
notify只会唤醒其中一个线程,
notifyAll则会唤醒全部线程。
至于notify会唤醒哪个线程,是由线程调度器决定的。
例子:
public class TestWaitAndnotify {
public static void main(String[] args) {
demo2();
}
public static void demo2 () {
final Object lock = new Object();
Thread A = new Thread(new Runnable(){
@Override
public void run() {
System.out.println("INFO: A 等待锁 ");
synchronized (lock) {
System.out.println("INFO: A 得到了锁 lock");
System.out.println("A1");
try {
System.out.println("INFO: A 准备进入等待状态,放弃锁 lock 的控制权 ");
lock.wait();//挂起线程A 放弃锁 lock 的控制权
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("INFO: 有人唤醒了 A, A 重新获得锁 lock");
System.out.println("A2");
System.out.println("A3");
}
}
});
Thread B = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("INFO: B 等待锁 ");
synchronized (lock) {
System.out.println("INFO: B 得到了锁 lock");
System.out.println("B1");
System.out.println("B2");
System.out.println("B3");
System.out.println("INFO: B 打印完毕,调用 notify 方法 ");
lock.notify(); // notify()方法唤醒正在等待lock锁的线程A
System.out.println("线程 B do notify method 完毕");
}
}
});
A.start();
B.start();
}
}
输出:

生产者消费者例子:
import java.util.LinkedList;
import java.util.Queue;
public class ProducerAndConsumer {
private final int MAX_LEN = 3;
private Queue<Integer> queue = new LinkedList<Integer>();
class Producer extends Thread {
@Override
public void run() {
producer();
}
private void producer() {
while(true) {
synchronized (queue) {
if(queue.size() == MAX_LEN) {
System.out.println("当前队列满");
queue.notify();
try {
queue.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
queue.add(1);
queue.notify();
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("生产者又生产一条任务,当前队列长度为" + queue.size());
}
}
}
}
class Consumer extends Thread {
@Override
public void run() {
consumer();
}
private void consumer() {
while(true) {
synchronized (queue) {
if(queue.size() == 0) {
System.out.println("当前队列为空");
queue.notify();
try {
queue.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
queue.poll();
queue.notify();
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("消费者消费了一条任务,当前队列长度为" + queue.size());
}
}
}
}
public static void main(String[] args) {
ProducerAndConsumer pac = new ProducerAndConsumer();
Producer producer = pac.new Producer();
Consumer consumer = pac.new Consumer();
producer.start();
consumer.start();
}
}

一:Lock/condition/await(), signal(), signalAll()
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 ProducerAndConsumer1 {
private final int MAX_LEN = 3;
private Queue<Integer> queue = new LinkedList<Integer>();
final Lock lock = new ReentrantLock();
final Condition producerSignal = lock.newCondition();
final Condition consumerSignal = lock.newCondition();
class Producer extends Thread {
@Override
public void run() {
producer();
}
private void producer() {
while(true) {
lock.lock();
try {
if(queue.size() == MAX_LEN) {
System.out.println("当前队列满");
try {
consumerSignal.signal();
producerSignal.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
queue.add(1);
consumerSignal.signal();
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("生产者生产了一条任务,当前队列长度为" + queue.size());
} finally {
lock.unlock();
}
}
}
}
class Consumer extends Thread {
@Override
public void run() {
consumer();
}
private void consumer() {
while(true) {
lock.lock();
try {
if(queue.size() == 0) {
System.out.println("当前队列为空");
try {
producerSignal.signal();
consumerSignal.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
queue.poll();
producerSignal.signal();
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("消费者消费了一条任务,当前队列长度为" + queue.size());
} finally {
lock.unlock();
}
}
}
}
public static void main(String[] args) {
ProducerAndConsumer1 pac = new ProducerAndConsumer1();
Producer producer = pac.new Producer();
Consumer consumer = pac.new Consumer();
producer.start();
consumer.start();
}
}

分析: 这里共享的变量是queue,生产者消费者都需要修改这个queue,为了保证安全,需要一个个的来,用lock,lock()就保证了每次只有一个线程来操作queue;
在生产和消费的时候,需要关心queue.size()的大小,如果满了,就不能生产,这里用了producerSignal.await(),让生产者放弃锁,去等待消费者去消费,consumerSignal.signal()去唤醒消费者去消费,如果空了,就不能消费, 这里用consumerSignal.await(),让消费者放弃锁,去等待生产者去生产,producerSignal.signal()去唤醒生产者去生产。
来源:https://www.cnblogs.com/myseries/p/12103723.html