synchronized
synchronized (临界资源) {
// 访问临界资源的代码
}
上述代码的作用是给临界资源“加锁”,其他线程访问临界资源会被阻塞,目的是保证同一时间只有一个线程访问临界区。
wait
临界资源.wait();
某个线程调用了临界资源的wait方法后,该线程被阻塞,直到被其他线程唤醒才能继续执行。
notify
临界资源.notify();
某个线程执行该方法后,随机唤醒一个试图访问临界区但处于阻塞状态的线程。
完整代码 demo.java
import java.util.LinkedList;
import java.util.Queue;
public class demo {
Queue<Integer> 临界资源 = new LinkedList<>();
final int MAX = 10;
public static void main(String[] args) {
demo d = new demo();
生产者 producer = d.new 生产者();
消费者 consumer = d.new 消费者();
producer.start();
consumer.start();
}
class 生产者 extends Thread {
@Override
public void run() {
while (true) { // 每隔0.5s生产一个商品
synchronized (临界资源) { // 临界资源被占用,其他线程访问临界资源将被阻塞
while (临界资源.size() == MAX) { // 临界区已满,唤醒消费者线程,阻塞生产者线程,此处不用 if 是为了保险
临界资源.notify(); // 唤醒试图访问临界资源的阻塞线程
System.out.println("临界区已满");
try {
临界资源.wait(); // 阻塞当前线程,等待其他线程唤醒
} catch (InterruptedException e) {
e.printStackTrace();
}
}
临界资源.add(1); // 生产一个商品
临界资源.notify(); // 唤醒消费者
System.out.println("已生产1件商品,当前商品数量:" + 临界资源.size());
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
class 消费者 extends Thread {
@Override
public void run() {
while (true) { // 每隔0.5秒消耗一个商品
synchronized (临界资源) {
while (临界资源.size() == 0) { // 资源耗尽
临界资源.notify();
System.out.println("临界资源耗尽");
try {
临界资源.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
临界资源.poll(); // 消耗一个商品
临界资源.notify(); // 唤醒生产者
System.out.println("已消耗1件商品,当前商品数量:" + 临界资源.size());
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
}