前言
本次文章主要讲解的是多线程的通信问题(生产者与消费者之间的关系)。
提示:以下是本篇文章正文内容,下面案例可供参考
一、运用到的方法
方法 | 描述 |
---|---|
wait() | 作用是释放锁,使其它线程可运行,本次线程进入等待池中,注意需要在synchronized语句块中使用 |
notifyAll() | 是将等待池中移走所有等待当前对象的线程并放入锁池中,使他们争夺锁 |
二、代码演示
代码如下:
/**
* 这是多线程之间的通信问题(生产者与消费者之间的)
* 主要定义了两个线程:
* 1、厨师线程----Cook
* 2、服务员线程----Writer
* 一个食物类------Food
* 如何实现线程之间的通信?
* 1、定义两个线程的构造方法,其中传入Food f ,在main线程中创建一个Food f 传入
* 2、定义两个线程的私有成员变量Food f,并且将形参的值赋值给该私有的成员,变量确保他们操作的是同一个对象
* 如何保证他们通信而不乱?
* 基本思想:厨师做饭时,服务员睡眠。厨师睡眠,服务员端饭。往复如此
* 实现思路:
* 1、将厨师做饭和服务员端饭的方法都加上snychronized关键字,确保只有一个线程在操作(因为此时的锁是this,即是此时的f)
* 问题:
* 但是厨师线程有可能回手掏再次夺取锁获取执行权限?
* 解决:
* 加上一个flag,当为true时厨师线程操作,操作完后flag改为false。
* 同理为flase时,服务员线程操作,操作完后flag改为true。
* 问题:
* 厨师线程可能一直抢到着锁,但由于此时flag为false执行不了,极大的降低了效率
* 解决:
* 当厨师线程完成操作后,notifyall(唤醒等待池中的所有等待当前对象的线程,进入锁池,因为只有进入锁池才能够获取锁),
* 然后执行wait(该方法会释放锁,并且进入等待池),服务员线程也是如此。
*/
public class ThreadTalk {
public static void main(String[] args) {
Food f = new Food();
new Cook(f).start();
new Writer(f).start();
}
}
class Cook extends Thread {
Food f;
Cook(Food f){
this.f = f;
}
@Override
public void run() {
for (int i=0;i<10;i++){
if(i%2==0){
f.getAndSet("老干妈小米粥","香辣味儿");
}else{
f.getAndSet("煎饼果子","甜辣味");
}
}
}
}
class Writer extends Thread{
Food f ;
Writer(Food f){
this.f = f;
}
@Override
public void run() {
for (int i=0;i<10;i++){
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
f.getAll();
}
}
}
class Food{
private String name;
private String taste;
boolean flag =true;
public synchronized void getAndSet(String name,String taste){
if(flag) {
this.name = name;
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
this.taste = taste;
flag = false;
}
notifyAll();
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public synchronized void getAll(){
if(!flag) {
System.out.println("菜名是:" + name + ",味道是:" + taste);
flag = true;
}
notifyAll();
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
总结
这就是本次的多线程之间的通信问题。