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线程是一块难点,本人学的也不精,欢迎一起探讨。