最近找工作,被问了很多多线程和锁的知识,这里总结一下多线程中wait()与notify()的用法。
直接上代码(生产者/消费者模式:代码来自马士兵老师):
public class ProducerConsumer {
public static void main(String[] args) {
SyncStack ss = new SyncStack();
Producer p1 = new Producer(ss, "p1");
Producer p2 = new Producer(ss, "p2");
Consumer c1 = new Consumer(ss, "c1");
Consumer c2 = new Consumer(ss, "c2");
new Thread(p1).start();
new Thread(p2).start();
new Thread(c1).start();
new Thread(c2).start();
}
}
class WoTou {
int id;
public WoTou(int id) {
this.id = id;
}
public String toString() {
return "WoTou:" + id;
}
}
//放窝头的篮子
class SyncStack {
int index = 0;
WoTou[] arrWoTou = new WoTou[6];
public synchronized void push(WoTou wt) {
while (index == arrWoTou.length) {
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
this.notify();
arrWoTou[index] = wt;
index++;
}
public synchronized WoTou pop() {
while (index == 0) {
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
this.notify();
index--;
return arrWoTou[index];
}
}
class Producer implements Runnable {
SyncStack ss = null;
String name;
Producer(SyncStack ss, String name) {
this.ss = ss;
this.name = name;
}
public void run() {
for (int i = 0; i < 20; i++) {
WoTou wt = new WoTou(i);
ss.push(wt);
System.out.println("procude_" + name + " : "+ wt);
try {
Thread.sleep((int) (Math.random() * 200));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class Consumer implements Runnable {
SyncStack ss = null;
String name;
Consumer(SyncStack ss, String name) {
this.ss = ss;
this.name = name;
}
public void run() {
for (int i = 0; i < 20; i++) {
WoTou wt;
wt = ss.pop();
System.out.println("consume_" + name + " : "+ wt);
try {
Thread.sleep((int) (Math.random() * 1000));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
1、wait() 和 notify()必须在有加锁的时候才能使用;
2、this.wait()不是指当前对象等待,而是指持有当前对象的线程等待!!!
3、notify()是指:调用notify方法的当前线程1,叫醒等待在线程1持有的对象上(上面例子中的ss对象)的另外一个线程;
4、notifyAll()就是叫醒等待ss对象上的其他所有线程,一起去抢对象ss的锁!