案例:
生产与消费分别开一个线程,生产一个产品消费一个产品,依次执行。
public class ThreadDemo { public static void main(String[] args) { Resource r = new Resource(); Producer producer = new Producer(r); Consumer consumer = new Consumer(r); Thread t1 = new Thread(producer); Thread t2 = new Thread(consumer); t1.start(); t2.start(); } } class Resource { private String name; private int count = 1; private boolean flag = false; public synchronized void set(String name) {//如果只有一个同步函数,可以使用同步函数,即在函数上加synchronzied。同步函数使用的锁是this。而当线程任务中需要多个同步时,必须用同步代码块,同步代码块使用的锁可以是任意对象。 if (flag) { try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } this.name = name + count; this.count++; System.out.println(Thread.currentThread().getName() + " 生产者 " + this.name); flag = true; this.notify(); } public synchronized void out() { if (!flag) { try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println(Thread.currentThread().getName() + " 消费者 " + this.name); flag = false; this.notify(); } } class Producer implements Runnable { private Resource r; public Producer(Resource r) { this.r = r; } public void run() { while (true) { r.set("面包"); } } } class Consumer implements Runnable { private Resource r; public Consumer(Resource r) { super(); this.r = r; } public void run() { while (true) { r.out(); } } }
等待唤醒机制:
wait(); 会让线程处于等待状态,其实就是将线程临时存储到了线程池中。(wait上面必须要有锁,即synchronized同步函数,线程池是靠锁划分的。)
notify(); 会唤醒此线程池中任意一个等待的线程。
notifyAll(); 会唤醒线程池中所有的等待线程。
记住:上面的方法必须使用在同步中,因为必须要标识这些方法所属的锁。同一个锁上的notify只能唤醒该锁上的被wai的线程。
为什么这些方法定义在Object类中呢?
因为这些方法必须标识所属的锁,而锁可以是任意对象,任意对象可以调用的方法必然是Object类中的方法。