Java线程交互的三个方法(四)

Java中除了使用synchronized 同步以外,经常还使用java.lang.Object提供的三个方法wait()、 notify()、 notifyAll()三个方法完成更高级和精确的交互操作。

Java线程涉及的三个方法:

wait(): 导致当前的正在运行的线程等待,直到其他线程调用此对象的 notify() 方法或notifyAll() 方法。

notify() :唤醒在此对象监视器上等待的单个线程。

notifyAll():唤醒在此对象监视器上等待的所有线程。

这三种方法是对线程直接操作,也必须保证“单操作性”,所以必须写在synchronized 的范围下。

其中,notify()和notifyAll()的用法是差不多的,一个唤醒的是单个线程,一个唤醒的是全部线程。

遵循以下的使用模型VIP

模型A,在一个线程中等待和相关操作,另一个线程中唤醒:
在一个线程中
synchronized (this ) {
    if (!condition) {// 当条件不满足时,执行wait()方法
        wait();
    }
    // 当条件满足时,执行相关操作
    doBThreadthing();
}

在另外一个线程中
synchronized (this ) {
    notify();
}

模型B,两个线程都有等待,唤醒和相关操作,只是条件相反:
synchronized (this ) {
    if (condition) {// 当条件不满足时,执行wait()方法
        wait();
    }
    // 当条件满足时,执行相关操作
    doBThreadthing();
    notify();
}

模型B实现了,两个线程完整的交互操作,著名的生产者和消费者模型就是使用了这个。

在生产者和消费者模型中,生产者和消费者是两个独立的线程,具有以下几个交互规则:

1、生产者生成资源供消费者使用
2、生产者生产时,消费者等待
3、消费者消费时生产者等待
4、消费者使用完毕,唤醒生产者
5、生产者生产完毕,唤醒消费者

class MyProducer extends Thread {
	Storage storage;

	public MyProducer(Storage storage) {
		this.storage = storage;
	}

	@Override
	public void run() {
		storage.produce();
	}

}

class MyConsumer extends Thread {
	Storage storage;

	public MyConsumer(Storage storage) {
		this.storage = storage;
	}

	@Override
	public void run() {
		while (true) {
			storage.consume();
		}
	}

}

class Storage {
	//将生产者和消费者的方法写到一个类当中,是为了使两个线程操作一个list对象,如果将list传入每个线程当中,操作的不是一个list对象。
	List<String> mList = new ArrayList<String>();

	public void produce() {
		synchronized (this) {
			for (int i = 1; i < 5; i++) {
				if (mList.size() != 0) {
					try {
						System.out.println("生产者在等待");
						wait();
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
				for (int j = 0; j <= i; j++) {
					mList.add("蛋糕");
				}
				System.out.println("生产者生产了" + i + "块蛋糕");
				notify();
			}
		}
	}

	public void consume() {
		synchronized (this) {
			if (mList.size() == 0) {
				try {
					System.out.println("消费者在等待");
					wait();
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			for(int i = 1 ; i < mList.size(); i++){
				System.out.println("消费者消费了第" + (i) + "块蛋糕");
			}
			mList.clear();
			notify();
		}
	}
}

public class Module {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		Storage storage = new Storage();
		MyProducer myProducer = new MyProducer(storage);
		MyConsumer myConsumer = new MyConsumer(storage);
		myConsumer.start();
		myProducer.start();
	}

}

运行结果:


Java线程是一块难点,本人学的也不精,欢迎一起探讨。



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章