1、线程间通信
概念:多线程在处理同一个资源,但是处理的动作却不相同。
为什么处理线程间通信?
多线程并发执行时,在默认情况下CPU是随机切换线程的,当我们需要多线程来共同完成一件任务,并且我们希望他们有规律的执行,那么多线程之间需要一些协调通信,以此来帮我们达到多线程共同操作一份数据。
如何保证线程间通信有效利用资源?
2、等待唤醒机制
概念:这是多线程间的协作机制。谈到线程我们经常想到的是线程间的竞争,比如去争夺锁,但这并不是故事的全部,线程间也会有协作机制。就好比在公司里你和你的同事们,你们可能存在晋升的竞争,但更多时候你们更多是一起合作完成某些任务。
就是在一个线程金信诺过了规定操作后,就进入等待状态(wait()),等待其他线程执行完他们的指定代码过后再将其唤醒(notify());在有多个线程进行等待时,如果需要,可以使用notify All()来唤醒所有的等待线程。wait/notify就是线程间的一种协作机制。
等待唤醒中的方法:
等待唤醒机制就是解决线程间通信的问题的,使用到的3个方法的含义如下:
1、wait:线程不再活动,不再参与调度,进入wait set中,因此不会浪费cup资源,也不会去竞争锁了,这时的线程状态即是waiting。它还要等着别的线程执行一个特别的动作,就是通知(notify)在这个对象上等待的线程从wait set中释放出来,重新进入调度队列(ready queue)中。
2、notify:则选取所有通知对象的wiat set 中的一个线程释放;例如,餐馆有空位置后,等候就餐最久的顾客最先入座。
3、notifyAll:则释放所通知对象的wait set 上的全部线程。
包子类:
public class BaoZi {
private String pi;
private String xian;
private boolean flag;
public BaoZi() {
}
public BaoZi(String pi, String xian, boolean flag) {
this.pi = pi;
this.xian = xian;
this.flag = 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;
}
}
包子铺:
public class BaoZiPu implements Runnable {
private BaoZi bz;
public BaoZiPu() {
}
public BaoZiPu(BaoZi bz) {
this.bz = bz;
}
//生产包子
@Override
public void run() {
int count = 0;
while (true){
synchronized (bz){
//对包子的状态进行判断
if (bz.isFlag()){
//包子铺调用wait方法进入等待状态,让客人吃包子
try {
bz.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//被唤醒之后执行,包子铺生产包子
if (count%2==0){
bz.setPi("薄皮");
bz.setXian("三鲜");
}else{
bz.setPi("厚皮");
bz.setXian("牛肉大葱");
}
count++;
System.out.println("包子铺正在生产:"+bz.getPi()+bz.getXian()+"包子");
//生产包子
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//包子好了后,修改状态
bz.setFlag(true);
bz.notify();//唤醒客人的线程
System.out.println("包子生产完毕");
}
}
}
}
客人:
public class ChiHuo implements Runnable {
private BaoZi baoZi;
public ChiHuo() {
}
public ChiHuo(BaoZi baoZi) {
this.baoZi = baoZi;
}
public BaoZi getBaoZi() {
return baoZi;
}
public void setBaoZi(BaoZi baoZi) {
this.baoZi = baoZi;
}
@Override
public void run() {
while (true){
synchronized (baoZi){
if(baoZi.isFlag()==false){
//客人等待包子做好
try {
baoZi.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//唤醒之后,吃包子
System.out.println("吃"+baoZi.getPi()+baoZi.getXian()+"的包子");
baoZi.setFlag(false);//包子吃完了
baoZi.notify();//唤醒去做包子
System.out.println("包子吃完了");
}
}
}
}
测试:
public class Demo05Main {
public static void main(String[] args) {
//创建包子对象
BaoZi baoZi = new BaoZi();
BaoZiPu baoZiPu = new BaoZiPu(baoZi);
new Thread(baoZiPu).start();
ChiHuo chiHuo = new ChiHuo(baoZi);
new Thread(chiHuo).start();
}
}