线程通信初始

简单认识一下线程通信

目录

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

线程通信定义

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

线程通信模型之一

释疑示例


案例

案例要求

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

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

参考视频

黑马磊哥


相关推荐
哈基米喜欢哈哈哈9 分钟前
低版本的JVM遇到高版本的class字节码是否会报错
java·jvm
2351613 分钟前
【并发编程】详解volatile
java·开发语言·jvm·分布式·后端·并发编程·原理
洛小豆40 分钟前
java 中 char 类型变量能不能储存一个中文的汉字,为什么?
java·后端·面试
爱吃烤鸡翅的酸菜鱼1 小时前
从数据库直连到缓存预热:城市列表查询的性能优化全流程
java·数据库·后端·spring·个人开发
一只学java的小汉堡1 小时前
Java 面试高频题:HashMap 与 ConcurrentHashMap 深度解析(含 JDK1.8 优化与线程安全原理)
java·开发语言·面试
huohaiyu2 小时前
Hashtable,HashMap,ConcurrentHashMap之间的区别
java·开发语言·多线程·哈希
信奥卷王3 小时前
[GESP202503 五级] 原根判断
java·数据结构·算法
小咕聊编程3 小时前
【含文档+源码】基于SpringBoot的过滤协同算法之网上服装商城设计与实现
java·spring boot·后端
Zz_waiting.3 小时前
Spring 原理
java·spring·spring自动管理
瓯雅爱分享7 小时前
Java+Vue构建的采购招投标一体化管理系统,集成招标计划、投标审核、在线竞价、中标公示及合同跟踪功能,附完整源码,助力企业实现采购全流程自动化与规范化
java·mysql·vue·软件工程·源代码管理