wait()方法和notify()方法的典型应用-生产者与消费者

/ 多线程 / 没有评论 / 332浏览

在多线程开发中最典型的应用就是生产者与消费者案例,主要用到的方法就是wait()方法和notify()方法。下面我们先看一下它们具体的业务代码。

/**
* 库存
*
* @author Sama
* @author admin@jilinwula.com
* @date 2017-03-20 11:43
* @since 1.0.0
*/
public class Stock {

private List<JSONObject> stocks = Collections.synchronizedList(new ArrayList<JSONObject>());

/**
* 生产
*
* @param jsonObject
*/
public void produce(JSONObject jsonObject) {
try {
synchronized (stocks) {
if (stocks.size() >= 10) {
stocks.wait();
}
if (stocks.size() > 0) {
stocks.notify();
}
stocks.add(jsonObject);
System.out.println(String.format("库存:%s\t生产:json: %s\tthread: %s", stocks.size(), jsonObject.toJSONString(), Thread.currentThread().getName()));
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}

/**
* 消费
*
* @param jsonObject
*/
public void consume(JSONObject jsonObject) {
try {
synchronized (stocks) {
if (stocks.size() == 0) {
stocks.notify();
stocks.wait();
}
stocks.remove(jsonObject);
System.out.println(String.format("库存:%s\t消费:json: %s\tthread: %s", stocks.size(), jsonObject.toJSONString(), Thread.currentThread().getName()));
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}

}
/**
* 生产者
*
* @author Sama
* @author admin@jilinwula.com
* @date 2017-03-20 11:55
* @since 1.0.0
*/
public class Producer extends Thread {

private Stock stock;

public Producer(Stock stock) {
this.stock = stock;
}

@Override
public void run() {
for (int i = 1; i <= 15; i++) {
JSONObject jsonObject = new JSONObject();
jsonObject.put("name", String.format("奔驰-%s", i));
stock.produce(jsonObject);
}
}
}
/**
* 消费者
*
* @author Sama
* @author admin@jilinwula.com
* @date 2017-03-20 11:55
* @since 1.0.0
*/
public class Customer extends Thread {

private Stock stock;

public Customer(Stock stock) {
this.stock = stock;
}

@Override
public void run() {
for (int i = 1; i <= 15; i++) {
JSONObject jsonObject = new JSONObject();
jsonObject.put("name", String.format("奔驰-%s", i));
stock.consume(jsonObject);
}
}
}
/**
* @author Sama
* @author admin@jilinwula.com
* @date 2017-03-20 13:35
* @since 1.0.0
*/
public class Test {
public static void main(String[] args) throws InterruptedException {
Stock stock = new Stock();
Producer producer = new Producer(stock);
Customer customer = new Customer(stock);
producer.start();
Thread.sleep(1000);
for (int i = 3; i > 0; i--) {
System.out.println(String.format("倒计时:%s", i));
Thread.sleep(1000);
}
customer.start();
}
}
库存:1	生产:json: {"name":"奔驰-1"}	thread: Thread-0
库存:2	生产:json: {"name":"奔驰-2"}	thread: Thread-0
库存:3	生产:json: {"name":"奔驰-3"}	thread: Thread-0
库存:4	生产:json: {"name":"奔驰-4"}	thread: Thread-0
库存:5	生产:json: {"name":"奔驰-5"}	thread: Thread-0
库存:6	生产:json: {"name":"奔驰-6"}	thread: Thread-0
库存:7	生产:json: {"name":"奔驰-7"}	thread: Thread-0
库存:8	生产:json: {"name":"奔驰-8"}	thread: Thread-0
库存:9	生产:json: {"name":"奔驰-9"}	thread: Thread-0
库存:10	生产:json: {"name":"奔驰-10"}	thread: Thread-0
倒计时:3
倒计时:2
倒计时:1
库存:9	消费:json: {"name":"奔驰-1"}	thread: Thread-1
库存:8	消费:json: {"name":"奔驰-2"}	thread: Thread-1
库存:7	消费:json: {"name":"奔驰-3"}	thread: Thread-1
库存:6	消费:json: {"name":"奔驰-4"}	thread: Thread-1
库存:5	消费:json: {"name":"奔驰-5"}	thread: Thread-1
库存:4	消费:json: {"name":"奔驰-6"}	thread: Thread-1
库存:3	消费:json: {"name":"奔驰-7"}	thread: Thread-1
库存:2	消费:json: {"name":"奔驰-8"}	thread: Thread-1
库存:1	消费:json: {"name":"奔驰-9"}	thread: Thread-1
库存:0	消费:json: {"name":"奔驰-10"}	thread: Thread-1
库存:1	生产:json: {"name":"奔驰-11"}	thread: Thread-0
库存:2	生产:json: {"name":"奔驰-12"}	thread: Thread-0
库存:1	消费:json: {"name":"奔驰-11"}	thread: Thread-1
库存:0	消费:json: {"name":"奔驰-12"}	thread: Thread-1
库存:1	生产:json: {"name":"奔驰-13"}	thread: Thread-0
库存:0	消费:json: {"name":"奔驰-13"}	thread: Thread-1
库存:1	生产:json: {"name":"奔驰-14"}	thread: Thread-0
库存:2	生产:json: {"name":"奔驰-15"}	thread: Thread-0
库存:1	消费:json: {"name":"奔驰-14"}	thread: Thread-1
库存:0	消费:json: {"name":"奔驰-15"}	thread: Thread-1

我们主要的逻辑是开启两个线程一个是生产线程一个是消费线程。当生产线程生产的库存超过10个时,暂停执行,目的是怕生产过剩。这时就只有一个消费线程在执行。当消费线程消费到库存为0时暂停消费线程,因为库存为0时不能在继续消费了。除了暂停消费线程外还调用了notify()方法目的是让生产线程继续生产。这时只有一个生产线程在执行,当生产线程生产库存大于0时,继续调用notify()方法,目的是让消费线程执行,因为库存不为0可以消费。这些就有两个线程同时执行了,这就是典型的生产者与消费者案例。