1.wait()与notify()/notifyAll()
调用sleep()和yield()的时候锁并没有被释放,而调用wait()将释放锁。这样另一个任务(线程)可以获得当前对象的锁,从而进入它的synchronized方法中。可以通过notify()/notifyAll(),或者时间到期,从wait()中恢复执行。
只能在同步控制方法或同步块中调用wait()、notify()和notifyAll()。
如果在非同步的方法里调用这些方法,在运行时会抛出IllegalMonitorStateException异常。
2.一般建议使用notifyAll()替代notify()。
Example:
简单模型:
门票生产者:Production
门票购买者:Operation
售票中心:TicketOffice
门票:Ticket
功能说明:
售票中心的门票最大库存10000张,最小库存100张,当大于最大库存时售票中心将不再购买门票,当小于最小库存售票中心则通知门票生产者生产门票并主动运输给售票中心。
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
/**
*
* 售票中心
*
* @author ZAKAI
*
*/
public class TicketOffice {
private BlockingQueue<Ticket> queue = new LinkedBlockingQueue<Ticket>();
/**
* 售票最大存货
*/
private static final int MAX = 10000;
private static final int MIN = 100;
/**
* 存入入场票
*
* @param t
* 门票实体
* @throws InterruptedException
* 异常实体
*/
public void storeTicket(final Ticket t) throws InterruptedException {
synchronized (this) {
if (!queue.isEmpty()) {
while (TicketOffice.MAX < queue.size()) {
System.out.println("售票中心:存票太多了,暂停进货...目前存票有:"
+ queue.size() + "张!");
notify();
wait();
}
System.out.println("售票中心:进货中..目前存票有:" + queue.size() + "张!");
}
}
queue.put(t);
}
/**
* 卖出入场票
*
* @return 门票
* @throws InterruptedException
* 异常实体
*/
public Ticket sellOut() throws InterruptedException {
synchronized (this) {
while (queue.isEmpty()) {
System.out.println("售票中心:票卖完了,等待进货...");
notify();
wait();
}
// 当库存小于最小库存数量开始开始通知生产者生产
if (TicketOffice.MIN > queue.size()) {
System.out.println("售票中心:票的数量低于最小库存了,通知门票生产者送货上门...");
notify();
}
}
return queue.take();
}
}
/**
*
* 门票生产者
*
* @author ZAKAI
*
*/
public class Production implements Runnable {
private static int id = 1;
private TicketOffice ticketOffice = null;
public Production(TicketOffice ticketOffice) {
this.ticketOffice = ticketOffice;
}
public void run() {
for (;;) {
try {
ticketOffice.storeTicket(making());
} catch (InterruptedException e1) {
e1.printStackTrace();
}
}
}
private Ticket making() {
Ticket t = new Ticket(++id);
System.out.println("门票制造商:已经制造票一张");
return t;
}
}
/**
*
* 门票购买者
*
* @author ZAKAI
*
*/
public class Operation implements Runnable {
/**
* 售票中心
*/
private TicketOffice ticketOffice = null;
public Operation(TicketOffice ticketOffice) {
this.ticketOffice = ticketOffice;
}
public void run() {
for (;;) {
try {
buy();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
/**
*
*
* 到售票中心购买门票
*
* @throws InterruptedException
*/
public void buy() throws InterruptedException {
System.out.println(" 门票购买者:买票中...");
Ticket t = ticketOffice.sellOut();
System.out.println("门票购买者:" + t + " 票被买到了...");
}
}
/**
*
* 门票实体
*
* @author ZAKAI
*
*/
public class Ticket {
/**
* 门票标识号
*/
private int id;
public Ticket(int id) {
this.id = id;
}
public String toString() {
StringBuffer sb = new StringBuffer();
sb.append("ticket id ").append(id);
return sb.toString();
}
}
public class Main {
public static void main(String args[]) {
final TicketOffice ticketOffice = new TicketOffice();
Thread productionTrd = new Thread(new Production(ticketOffice));
Thread operationTrd = new Thread(new Operation(ticketOffice));
productionTrd.start();
operationTrd.start();
}
}