1. 使用注意事项
- 只能在synchronized关键字中调用 wait()方法、notify()系列方法
- 尽可能用 notifyall(),因notify()只能唤醒一个线程,不确定是哪一个线程
2. 示例
2.1 生产者
private Integer zd = 0; // 定义子弹变量// 生产者生产子弹public synchronized void set(){while ( zd >= 20 ) {try {System.out.println(Thread.currentThread().getName() + \"子弹已经装满了\");wait();} catch (InterruptedException e) {e.printStackTrace();}}zd++;System.out.println(Thread.currentThread().getName() + \" 装入子弹一枚\");// 唤醒所有在wait状态的线程,可能消费者也处于wait状态,唤醒,进行消费子弹notifyAll();}// 生产者线程生产子弹public static class producer implements Runnable{Task task;public producer(Task task) {this.task = task;}@Overridepublic void run() {// do my workwhile (true) {// 生产者一直去调用set,生产子弹task.set();try {Thread.sleep(6);} catch (InterruptedException e) {e.printStackTrace();}}}}
2.2 消费者
private Integer zd = 0; // 定义子弹变量// 消费者消费子弹public synchronized void get(){while ( zd <= 0 ) {try {System.out.println(Thread.currentThread().getName() + \" 子弹已经射完了\" );wait();} catch (InterruptedException e) {e.printStackTrace();}}zd--;System.out.println(Thread.currentThread().getName() + \" 发射一枚子弹\" );// 唤醒所有在wait状态的线程,可能生产者也处于wait状态,唤醒,进行生产子弹notifyAll();}// 消费者线程消费子弹public static class consumer implements Runnable{Task task;public consumer(Task task) {this.task = task;}@Overridepublic void run() {// do my workwhile (true) {// 消费者一直去调用get,消费子弹task.get();try {Thread.sleep(6);} catch (InterruptedException e) {e.printStackTrace();}}}}
2.3 启动类
public static void main(String[] args) {Task task = new Task();// 开启10个生产者线程for (int i = 0; i < 10; i++) {new Thread(new producer(task), \"生产者: \" + i).start();}// 开启10个消费者线程for (int i = 0; i < 10; i++) {new Thread(new consumer(task), \"消费者: \" + i).start();}}
3. 完整代码
public class Task {/*分析:生产者需要检测枪膛是不是还有子弹,如果子弹不满,则添加子弹(子弹+1), 需要唤醒处于wait状态的消费者,进行消费子弹,如果子弹满了,则等待子弹的消耗(子弹-1)消费者需要检测枪膛是不是还有子弹,如果有子弹,则使用子弹(子弹-1),需要唤醒处于wait状态的生产者,进行生产子弹,如果没有子弹,则等待子弹的添加(子弹+1)*/private Integer zd = 0; // 定义子弹变量// 消费者消费子弹public synchronized void get(){while ( zd <= 0 ) {try {System.out.println(Thread.currentThread().getName() + \" 子弹已经射完了\");wait();} catch (InterruptedException e) {e.printStackTrace();}}zd--;System.out.println(Thread.currentThread().getName() + \" 发射一枚子弹\");// 唤醒所有在wait状态的线程,可能生产者也处于wait状态,唤醒,进行生产子弹notifyAll();}// 生产者生产子弹public synchronized void set(){while ( zd >= 20 ) {try {System.out.println(Thread.currentThread().getName() + \" 子弹已经装满了\");wait();} catch (InterruptedException e) {e.printStackTrace();}}zd++;System.out.println(Thread.currentThread().getName() + \" 装入子弹一枚\" );// 唤醒所有在wait状态的线程,可能消费者也处于wait状态,唤醒,进行消费子弹notifyAll();}// 消费者线程消费子弹public static class consumer implements Runnable{Task task;public consumer(Task task) {this.task = task;}@Overridepublic void run() {// do my workwhile (true) {// 消费者一直去调用get,消费子弹task.get();try {Thread.sleep(6);} catch (InterruptedException e) {e.printStackTrace();}}}}// 生产者线程生产子弹public static class producer implements Runnable{Task task;public producer(Task task) {this.task = task;}@Overridepublic void run() {// do my workwhile (true) {// 生产者一直去调用set,生产子弹task.set();try {Thread.sleep(6);} catch (InterruptedException e) {e.printStackTrace();}}}}// 入口函数public static void main(String[] args) {Task task = new Task();// 开启10个生产者线程for (int i = 0; i < 10; i++) {new Thread(new producer(task), \"生产者: \" + i).start();}// 开启10个消费者线程for (int i = 0; i < 10; i++) {new Thread(new consumer(task), \"消费者: \" + i).start();}}}