Thread之线程通信(wait和notify)


线程通信的定义

线程是程序中独立的个体,但这些个体如果不经过处理就不能成为一个整体。线程间的通信就是使它们成为整体的方案之一。
可以说通过线程通信,线程之间的交互性会更强大,能够大大提高CPU的复用率,同时也可以对线程任务进行有效的把控和监督

轮询实现

import lombok.SneakyThrows;
import java.util.ArrayList;
import java.util.List;
/**
 * 模拟厨师与服务员上菜
 * @author layman
 * @date 2021/2/7
 */
public class Demo10 {
    
    
    public static void main(String[] args) {
    
    
        Cook cook = new Cook();
        WaiterA threadA = new WaiterA(cook);
        threadA.start();
        WaiterB threadB = new WaiterB(cook);
        threadB.start();
    }
}
class Cook {
    
    
    //强制线程从公共堆栈获取数据
    public volatile List<Integer> meal = new ArrayList();
    public void add() throws InterruptedException {
    
    
        for (int i = 1; i < 8 ; i++) {
    
    
            meal.add(i);
            System.out.println("第 "+i+" 道菜做好了");
            Thread.sleep(1000);
        }
    }
}
class WaiterA extends  Thread{
    
    
    private Cook cook;
    public WaiterA(Cook cook){
    
    
        this.cook = cook;
    }
    @SneakyThrows
    @Override
    public void run() {
    
    
        while (true){
    
    
            cook.add();
        }
    }
}
class WaiterB extends  Thread{
    
    
    private Cook cook;
    public WaiterB(Cook cook){
    
    
        this.cook = cook;
    }
    @SneakyThrows
    @Override
    public void run() {
    
    
        while (true){
    
    
            if(cook.meal.size() == 5){
    
    
                System.out.println("1号桌5个菜已经做好了,准备上菜");
                throw new InterruptedException();
            }
        }
    }
}

运行结果
在这里插入图片描述

结论

在这里插入图片描述

wait和notify实现

在这里插入图片描述
重点 : wait()会释放对象锁在这里插入图片描述

wait方法

/**
 * 测试wait()只能在同步方法中调用
 */
public class TestWait {
    
    
    private String name = "layman";

    public void methodA() throws InterruptedException{
    
    
            name.wait();
    }
    public void methodB() throws InterruptedException {
    
    
        synchronized (name){
    
    
            name.wait();
        }
    }
    public static void main(String[] args) throws InterruptedException {
    
    
        TestWait tw = new TestWait();
        tw.methodA();  //Exception in thread "main" java.lang.IllegalMonitorStateException
     // tw.methodB();
    }
}

nofify方法

在这里插入图片描述

import lombok.SneakyThrows;

public class Demo12 {
    
    
    public static void main(String[] args) throws InterruptedException {
    
    
        Object obj = new Object();
        Demo12ThreadA threadA = new Demo12ThreadA(obj);
        threadA.start();
        //让主线程等待2秒钟
        Thread.sleep(2000);
        Demo12ThreadB threadB = new Demo12ThreadB(obj);
        threadB.start();
    }
}
class Demo12ThreadA extends  Thread{
    
    
    private Object lock;

    public  Demo12ThreadA(Object lock){
    
    
        setName("A线程");
        this.lock = lock;
    }

    @SneakyThrows
    @Override
    public void run() {
    
    
        synchronized (lock){
    
    
            System.out.println(Thread.currentThread().getName()+"进入等待,时间为:"+System.currentTimeMillis());
            lock.wait();
            System.out.println(Thread.currentThread().getName()+"结束等待,时间为:"+System.currentTimeMillis());
        }
    }
}
class Demo12ThreadB extends  Thread{
    
    
    private Object lock;

    public  Demo12ThreadB(Object lock){
    
    
        setName("B线程");
        this.lock = lock;
    }

    @SneakyThrows
    @Override
    public void run() {
    
    
        synchronized (lock){
    
    
            System.out.println(Thread.currentThread().getName()+"进行通知,时间为:"+System.currentTimeMillis());
            lock.notify();
            Thread.sleep(1000);
        }
    }
}

结论

  • wait()立刻释放对象锁,自身进入等待状态
  • notify()不会立刻释放对象锁,当同步代码块执行完毕后才会释放
  • 在这里插入图片描述
  • 在这里插入图片描述

补充说明

sleep(long millis)与wait(long timeout)的区别:sleep不会释放对象锁,而wait会

猜你喜欢

转载自blog.csdn.net/single_0910/article/details/113742962