关于Object类中的wait()和notify()方法(生产者和消费者模式):
1、首先,wait()和notify()方法不是线程对象的方法,是java中任何一个对象都有的方法,因为这两个方法是Object类中自带的。
2、这两个方法的作用:
(1)wait()方法的作用:
Object obj = new Object();
obj.wait();
表示:让正在obj对象上活动的当前线程进入等待状态,永久等待,直到被唤醒为止。
(2)notify()方法的作用:
Object obj = new Object();
obj.notify();
表示:唤醒正在obj对象上等待的当前线程。
还有一个notifyAll()方法:
这个方法是唤醒obj对象上处于等待的所有线程,并不会释放对象锁。
注意:wait()和notify()方法建立在synchronized线程同步的基础之上。
wait()方法会让正在obj对象上活动的当前线程进入等待状态,并且释放之前占有的对象锁。
notify()只会通知当前线程可以开始访问obj对象。
作业:多个线程操作一个仓库。
假设仓库用ArrayList集合,最多只能存储一个元素。1个就代表仓库满了。
必须做到:生产一个,消费一个。
测试代码:
import java.util.ArrayList;
import java.util.List; */
public class Test14 {
public static void main(String[] args) {
// 创建仓库对象,共享的
List<Product> list = new ArrayList();
// 创建生产者线程
Thread t1 = new Thread(new Producer(list));
// 创建消费者线程
Thread t2 = new Thread(new Consumer(list));
t1.setName("生产者线程");
t2.setName("消费者线程");
t1.start();
t2.start();
}
}
// 生产线程
class Producer implements Runnable {
List<Product> list; // 仓库
int i = 0; // 生产编号
public Producer(List list) {
this.list = list;
}
@Override
public void run() {
// 一直生产,死循环
while (true) {
synchronized (list) { // 生产和消费不能同时开始访问仓库
if (list.size() > 0) { // 仓库满了
try {
list.wait(); // 停止生产,并释放对象锁,消费者可以开始消费了
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// 程序能执行到这,说明仓库没有满,进行生产
// 模拟生产时间
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
// 产品生产出来,添加到仓库
Product p = new Product(++i);
list.add(p);
System.out.println(Thread.currentThread().getName() + "生产了" + p);
// 唤醒消费者进行消费
list.notifyAll();
}
}
}
}
// 消费线程
class Consumer implements Runnable {
List<Product> list; // 仓库
public Consumer(List list) {
this.list = list;
}
@Override
public void run() {
// 一直消费
while (true) {
synchronized (list) { // 生产和消费不能同时开始访问仓库
if (list.size() == 0) { // 仓库空了
try {
list.wait(); // 停止消费,并释放对象锁,生产者可以开始生产了
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// 程序能执行到这,说明仓库中有元素,进行消费
// 模拟消费时间
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
// 消费了产品,从仓库中移除产品
Product p = list.remove(0);
System.out.println(Thread.currentThread().getName() + "消费了" + p);
// 唤醒生产者进行生产
list.notifyAll();
}
}
}
}
class Product {
int id; // 产品编号
public Product(int id) {
this.id = id;
}
@Override
public String toString() {
return "product{" + "id=" + id + '}';
}
}
运行截图: