线程间通信
█ 针对同一个资源的操作有不同的线程
☞ 举例:买点影票有卖出的,也有退票的
█ Demo
☞ 通过生产线程 和消费线程,对一个生产对象进行操作。
等待唤醒机制
█ Object
>Wait() // 执行wait会自动释放锁
>Notify() //会唤醒其他等待进程,但是不会释放锁;通知其他进程可以执行,其他进程获得可以执行的一个条件进入同步阻塞,当进程获得锁的时候就进入就绪状态
>notifyAll()
为什么不定义在Thread类中?
//因为锁可以是任意对象。若以线程间通信机制的api必须所有对象都有
线程状态转换图
Baozi.java | TestMain.java |
package com.java.thread_PV;
public class Baozi {
private String name;
private String price;
private boolean flag; //flag 为false的时候表示没有数据,为true表示有数据;不初始化默认为FALSE
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPrice() {
return price;
}
public void setPrice(String price) {
this.price = price;
}
public Baozi(String name, String price) {
super();
this.name = name;
this.price = price;
}
public boolean isFlag() {
return flag;
}
public void setFlag(boolean flag) {
this.flag = flag;
}
}
|
package com.java.thread_PV;
public class TestMain {
public static void main(String[] args) {
Baozi baozi=new Baozi(null,null); //同一个对象,后面确保同一把锁
Producer producer=new Producer(baozi);
Customer customer=new Customer(baozi);
producer.start();
customer.start();
}
}
|
Producer.java | Customer.java |
package com.java.thread_PV;
public class Producer extends Thread {
Baozi baozi;
public Producer(Baozi baozi2) {
baozi = baozi2;
}
public void run() {
super.run();
int i = 0;
while (true) {
synchronized (baozi) { //notify 和 wait 机制需要放到同步代码快里使用
if (baozi.isFlag()) { // flag 为true表示有包子
// 等待 (放弃执行权,让其他线程执行。消费者去消费)
try {
baozi.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// 没有包子就生产
if (i % 2 == 0) {
baozi.setName("天津狗不理");
baozi.setPrice("10RMB");
} else {
baozi.setName("无锡灌汤包");
baozi.setPrice("5RMB");
}
i++;
// 生产完之后?改变标记flag为true,通知消费者来消费
baozi.setFlag(true);
baozi.notify(); // 通知消费者,但是消费者并不能立即执行;要等后面的代码全部执行完释放锁后,消费者进程抢到锁才能执行
}
}
}
}
|
package com.java.thread_PV;
public class Customer extends Thread {
Baozi baozi;
public Customer(Baozi baozi2) {
baozi = baozi2;
}
public void run() {
super.run();
while (true) {
synchronized (baozi) {
if (!baozi.isFlag()) { // false 表示没有包子,就等待
try {
baozi.wait(); //等待的时候放弃cpu执行权。。但是这里要释放锁!!这里wait方法会自动释放锁,所以不会形成死锁
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// 如果有就消费
System.out.println("Customer.consume()" + baozi.getName() + " :" + baozi.getPrice());
// 消费完就修改标记,通知生产者去生产
baozi.setFlag(false);
baozi.notify(); // 通知生产者,notify不会释放锁,如果下面还有代码,这里还会接着执行,不会释放锁;另外的进程不会拿到锁,会进入同步阻塞;拿到锁就进入就绪状态
}
}
}
}
|