在java中,线程间的通信可以使用wait、notify、notifyAll来进行控制。
虽然都是跟多线程相关的,但这3个方法并不是Thread类或者是Runnable接口的方法,而是Object类的3个本地方法。
因为在调用这3个方法的时候,当前线程必须获得这个对象的锁,但不是每个对象都是Thread。
关于对象锁,当多个线程都持有同一个对象的时候,如果都要进入synchronized(obj){……}的内部,就必须拿到这个对象的锁,
synchronized的机制保证了同一时间最多只能有1个线程拿到了对象的锁,
关于这3个方法的作用:
- wait:线程自动释放其占有的对象锁,并等待notify。
- notify:唤醒一个正在wait当前对象锁的线程,并让它拿到对象锁。
notify是本地方法,具体唤醒哪一个线程由虚拟机控制。
- notifyAll:唤醒所有正在wait当前对象锁的线程。
notifyAll后并不是所有的线程都能马上往下执行,它们只是跳出了wait状态,接下来它们还会是竞争对象锁。
示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
|
public class Consumer extends Thread{
private Producer producer;
public Consumer(String name,Producer producer){ super(name); this.producer = producer; }
@Override public void run() { Message message = producer.waitMsg(); System.out.println("Consumer " + getName() + " get a msg");
}
public static void main(String[] args) { Producer p = new Producer(); p.start(); new Consumer("Consumer1", p).start(); new Consumer("Consumer2", p).start(); new Consumer("Consumer3", p).start(); }
}
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
|
public class Producer extends Thread {
private final List<Message> mList = new ArrayList<>();
@Override public void run() { while (true){ try { System.out.println("生产者开始 3 秒休眠"); Thread.sleep(3000); Message message = new Message(); System.out.println("生产者开始产出 msg 实体"); synchronized (mList){ mList.add(message); mList.notify(); System.out.println("唤醒一个正在wait当前对象锁的线程,并让它拿到对象锁。"); } } catch (InterruptedException e) { e.printStackTrace(); } } }
public Message waitMsg(){ synchronized (mList){ if (mList.size() == 0){ try { System.out.println("消费者进入 wait 状态,线程自动释放其占有的对象锁,并等待notify。"); mList.wait(); System.out.println("消费者被 notify 唤醒"); } catch (InterruptedException e) { e.printStackTrace(); } } return mList.remove(0); } }
}
|
1 2 3 4 5 6 7 8
|
public class Message {
}
|