测试类:
public class Test01 {
public static void main(String[] args) {
MyStorage storage = new MyStorage();
Producer producer = new Producer(storage);
Consumer consumer = new Consumer(storage);
producer.setName("生产者");
consumer.setName("销售人员");
producer.start();
consumer.start();
}
}
/**
- 仓库类
- @author Administrator
*/
import java.util.LinkedList;
public class MyStorage {
LinkedList list = new LinkedList<>(); //存储产品
private static final int MAX_CAPACITY = 100; //仓库的最大容量
//存储产品 ,约定每次存10个产品
public synchronized void store() {
//仓库已满 ,生产者等待,等到消费者消费了后再继续生产
while ( list.size() >= MAX_CAPACITY) {
try {
this.wait(); //wait()/notify()只能在同步代码块中由锁对象调用
//执行wait(),线程等待,会释放锁对象,
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println( Thread.currentThread().getName() + "存储产品 前, 仓库容量:" + list.size());
for( int i =1; i <= 10;i++){
//offer属于 offer in interface Deque<E>,add 属于 add in interface Collection<E>。
//当队列为空时候,使用add方法会报错,而offer方法会返回false。都是添加
//作为List使用时,一般采用add / get方法来 压入/获取对象。
//作为Queue使用时,才会采用 offer/poll/take等方法作为链表对象时,offer等方法相对来说没有什么意义这些方法是用于支持队列应用的。
list.offer(new Object());
}
System.out.println( Thread.currentThread().getName() + "存了10个产品后, 仓库容量:" + list.size());
//通知消费者消费
this.notify();
}
//取产品 , 约定一次取10个
public synchronized void get() {
//判断仓库如果已空, 消费者需要等待, 等待生产者生产了产品后再继续消费
while ( list.size() <= 0) {
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println( Thread.currentThread().getName() + "消费 前, 仓库容量:" + list.size());
for( int i =1; i <= 10;i++){
//poll是减少的意思
list.poll();
}
System.out.println( Thread.currentThread().getName() + "消费了10个产品 后, 仓库容量:" + list.size());
//通知生产者生产
this.notifyAll();
/*notify和notifyAll的区别
如果线程调用了对象的 wait()方法,那么线程便会处于该对象的等待池中,等待池中的线程不会去竞争该对象的锁。
当有线程调用了对象的 notifyAll()方法(唤醒所有 wait 线程)或 notify()方法(只随机唤醒一个 wait 线程),被唤醒的的线程便会进入该对象的锁池中,锁池中的线程会去竞争该对象锁。也就是说,调用了notify后只要一个线程会由等待池进入锁池,而notifyAll会将该对象等待池内的所有线程移动到锁池中,等待锁竞争
优先级高的线程竞争到对象锁的概率大,假若某线程没有竞争到该对象锁,它还会留在锁池中,唯有线程再次调用 wait()方法,它才会重新回到等待池中。而竞争到对象锁的线程则继续往下执行,直到执行完了 synchronized 代码块,它会释放掉该对象锁,这时锁池中的线程会继续竞争该对象锁。
*/
}
}
/**
- 生产者线程
- @author Administrator
*/
public class Producer extends Thread {
MyStorage storage;
public Producer(MyStorage storage) {
super();
this.storage = storage;
}
@Override
public void run() {
//
for(int d = 1; d <= 200; d++){
storage.store();
}
}
}
/**
- 消费者线程
- @author Administrator
*/
public class Consumer extends Thread {
MyStorage storage;
public Consumer(MyStorage storage) {
super();
this.storage = storage;
}
@Override
public void run() {
//
for(int d = 1; d <= 200; d++){
storage.get();
}
}
}