1.线程间通信
2.等待唤醒机制
3.等待唤醒案例
3.1简单生产者消费者案例
分析:
代码:
Object类中的方法
void wait() 导致当前线程等待,直到另一个线程调用该对象的 notify()方法或 notifyAll()方法。
void notify() 唤醒正在等待对象监视器的单个线程。
package com.goldencis.thread;
/**
* 等待唤醒案例 :线程之间的通信
* 创建一个顾客进程(消费者):告知老板要的包子的种类和数量,调用wait方法,放弃cpu的执行,进入waiting状态(无限等待)
* 创建一个老板进程(生产者):花费5秒做包子,做好包子之后,调用notify方法,唤醒顾客吃包子
*
* 注意:
* 顾客和老板线程必须使用同步代码块包裹起来,保证等待和唤醒只有一个在执行
* 同步使用的锁对象必须保证唯一
* 只有锁对象才能调用wait和notify方法
*
* Object类中的方法
* void wait() 导致当前线程等待,直到另一个线程调用该对象的 notify()方法或 notifyAll()方法。
* void notify() 唤醒正在等待对象监视器的单个线程。
*/
public class DemoWaitAndNotify {
public static void main(String[] args) {
//锁对象
Object obj = new Object();
//创建一个顾客进程(消费者)
new Thread(){
@Override
public void run() {
synchronized (obj){
while(true){
//告知老板要的包子的种类和数量
System.out.println("告知老板要的包子的种类和数量");
//调用wait方法,放弃cpu的执行,进入waiting状态(无限等待)
try {
obj.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("吃包子咯");
}
}
}
}.start();
//创建一个老板进程(生产者)
new Thread(){
//做好包子之后,调用notify方法,唤醒顾客吃包子
@Override
public void run() {
while(true){
//花费5秒做包子,
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (obj){
System.out.println("老板花费5秒做包子,唤醒顾客吃包子");
obj.notify();
}
}
}
}.start();
}
}
进入计时等待有两种方式:
sleep(long m) 在毫秒值结束之后,线程睡醒进入Runnable/Blocked状态wait(long m) 如果在毫秒值结束之后,还没有被notify唤醒,就会自动醒来,线程睡醒进入Runnable/Blocked状态
唤醒方式:
notify() 唤醒正在等待对象监视器的单个线程notifyAll() 唤醒正在等待对象监视器的所有线程
3.2 生产者与消费者案例
分析:
代码:
包子类Bun.java
package com.goldencis.thread.BunPAC;
/**
* 包子类
*/
public class Bun {
String pi;
String xian;
boolean flag;//包子资源是否存在
public String getPi() {
return pi;
}
public void setPi(String pi) {
this.pi = pi;
}
public String getXian() {
return xian;
}
public void setXian(String xian) {
this.xian = xian;
}
public boolean isFlag() {
return flag;
}
public void setFlag(boolean flag) {
this.flag = flag;
}
}
生产者Producer.java
package com.goldencis.thread.BunPAC;
/**
* 生产者
*/
public class Producer extends Thread{
private Bun bun;//包子
private Object obj;//锁对象
public Producer(Bun bun, Object obj) {
this.bun = bun;
this.obj = obj;
}
@Override
public void run() {
while(true){
synchronized (obj){
//没有包子,生产包子
if(bun.flag == false){
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("包子铺生产了一个包子");
bun.flag = true;
obj.notify();//唤醒消费者
// 有包子,等待
}else{
try {
obj.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
}
Consumer.java
package com.goldencis.thread.BunPAC;
/**
* 消费者
*/
public class Consumer extends Thread{
private Bun bun;//包子
private Object obj;//锁对象
public Consumer(Bun bun, Object obj) {
this.bun = bun;
this.obj = obj;
}
@Override
public void run() {
while (true){
synchronized (obj){
//有包子,吃包子
if(bun.flag == true){
System.out.println("吃包子咯");
bun.flag = false;
obj.notify();//唤醒生产者
//没有包子,等待
}else{
try {
obj.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
}
测试类Test.java
package com.goldencis.thread.BunPAC;
public class Test {
public static void main(String[] args) {
Bun bun =new Bun();
bun.setFlag(false);
Object obj = new Object();
Producer p = new Producer(bun,obj);
Consumer c = new Consumer(bun,obj);
p.start();
c.start();
}
}
注:可以把包子(bun)作为锁对象,就不用创建Object对象了