线程通信初始

简单认识一下线程通信

目录

注:线程通信 前提是 线程安全

线程通信定义

当多个线程共同操作 共享的资源时,线程间 通过某种方式 互相告知自己的状态,以相互协调或完成某一项任务 ,并避免无效的资源争夺

线程通信模型之一

释疑示例


案例

案例要求

3个生产者 线程,负责生产 包子,每个线程每次只能 生产1个包子放在桌子上

2个消费者 线程负责吃 包子,每人每次只能 从桌子上拿1个包子吃

案例简单实现

操作模版类

java 复制代码
package com.xie.thread.communication;

import java.util.ArrayList;
import java.util.List;
/**
 * 容器--桌子,同时也是操作对象模版类   注:当前锁对象用this关键字来指定
 * */
public class Desk {
    private List<String> list = new ArrayList<>();
    /**
     * 放包子方法 操作对象:厨师1 厨师1 厨师3
     * */
    public synchronized void put() {
        // 获取当前执行的线程名
        String name = Thread.currentThread().getName();
        try {
            // 判断集合中是否有元素(包子)
            if (list.size() == 0) {
                list.add(name + "做的肉包子");
                System.out.println(name + "做了一个肉包子~~");
                // 模拟工作耗时,等待时间
                Thread.sleep(2000);
                // 唤醒别人,等待自己
                this.notifyAll();
                this.wait();
            }else {
                // 发现容器中有元素(包子)
                // 唤醒别人,等待自己
                this.notifyAll();
                this.wait();
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    /**
     * 取(或吃)包子方法 操作对象:吃货1 吃货2
     * */
    public synchronized void get() {
        // 获取当前执行的线程名
        String name = Thread.currentThread().getName();
        try {
            if (list.size() == 1) {
                // 取出元素(包子),代表吃了
                System.out.println(name + "吃了:" + list.get(0));
                list.clear();
                // 模拟吃的耗时
                Thread.sleep(1000);
                // 唤醒别人,等待自己
                this.notifyAll();
                this.wait();
            }else{
                // 发现容器中没有元素(包子),空的
                // 唤醒别人,等待自己
                this.notifyAll();
                this.wait();
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

测试

java 复制代码
package com.xie.thread.communication;

/**
 * 线程通信---消费者与生产者案例   注:下面的5个线程共用同一把锁!!!
 *
 * 案例要求:
 * 3个生产者线程,负责生产包子,每个线程每次只能生产1个包子放在桌子上
 * 2个消费者线程负责吃包子,每人每次只能从桌子上拿1个包子吃
 * */
public class ThreadTest {
    public static void main(String[] args) {
        /**创建操作对象*/
        Desk desk = new Desk();
        /**
         * 创建三个消费者线程,匿名内部类方式创建
         * */
        new Thread(() -> {
            while (true) {
                    desk.put();
            }
        }, "厨师1").start();

        new Thread(() -> {
            while (true) {
                desk.put();
            }
        }, "厨师2").start();

        new Thread(() -> {
            while (true) {
                desk.put();
            }
        }, "厨师3").start();

        /**
         * 创建两个生产者线程,匿名内部类方式创建
         * */
        new Thread(() -> {
            while (true) {
                desk.get();
            }
        }, "吃货1").start();

        new Thread(() -> {
            while (true) {
                desk.get();
            }
        }, "吃货2").start();
    }
}

拓展

等待和唤醒API

注:上述方法应该使用 当前同步锁对象 进行调用

参考视频

黑马磊哥


相关推荐
渣哥1 小时前
原来 Java 里线程安全集合有这么多种
java
间彧1 小时前
Spring Boot集成Spring Security完整指南
java
间彧1 小时前
Spring Secutiy基本原理及工作流程
java
Java水解2 小时前
JAVA经典面试题附答案(持续更新版)
java·后端·面试
洛小豆4 小时前
在Java中,Integer.parseInt和Integer.valueOf有什么区别
java·后端·面试
前端小张同学5 小时前
服务器上如何搭建jenkins 服务CI/CD😎😎
java·后端
ytadpole5 小时前
Spring Cloud Gateway:一次不规范 URL 引发的路由转发404问题排查
java·后端
华仔啊5 小时前
基于 RuoYi-Vue 轻松实现单用户登录功能,亲测有效
java·vue.js·后端
程序员鱼皮6 小时前
刚刚 Java 25 炸裂发布!让 Java 再次伟大
java·javascript·计算机·程序员·编程·开发·代码