Java多线程算法总结

news2024/11/17 5:28:19

1. 标题三个线程同时运行,依次打印ABC,一共打印10次

算法代码如下:

public class ThreadTest {

    private Object oa = new Object();
    private Object ob = new Object();
    private Object oc = new Object();

    private static final String TAG = "ThreadTest";

    private Runnable a = new Runnable() {
        @Override
        public void run() {
            int count  = 10;
            while (count > 0) {
                synchronized (oc) {  //首先需要等待上个线程执行打印后,才能执行自己线程的打印任务。因此要获取到上个对象锁,这里是oc,并且执行oc.wait()方法
                    //这样一旦在C线程中,oc执行了notify()方法后,才能按顺序让A线程继续执行

                    synchronized (oa) { // 为了唤醒下一个B线程,执行oa.notify()方法,那么就需要对oa加锁
                        Log.i(TAG, "A");
                        count --;
                        oa.notify();
                    }

                    try {
                        oc.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    };

    private Runnable b = new Runnable() {
        @Override
        public void run() {
            int count  = 10;
            while (count > 0) {
                synchronized (oa) {

                    synchronized (ob) {
                        Log.i(TAG, "B");
                        count --;
                        ob.notify();
                    }

                    try {
                        oa.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    };

    private Runnable c = new Runnable() {
        @Override
        public void run() {
            int count  = 10;
            while (count > 0) {
                synchronized (ob) {

                    synchronized (oc) {
                        Log.i(TAG, "C");
                        count --;
                        oc.notify();
                    }

                    try {
                        ob.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    };

    public void startThread() {
        Thread at = new Thread(a);
        Thread bt = new Thread(b);
        Thread ct = new Thread(c);


        try {
            at.start();
            Thread.sleep(100);  //保证第一次循环是ABC的顺序
            bt.start();
            Thread.sleep(100);
            ct.start();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

}

也可以把重复的Runnable抽象成一个,如下:

    private static class PrintRunnable implements Runnable {

        Object prev;
        Object current;
        String name;

        PrintRunnable(String name, Object prev, Object current) {
            this.name = name;
            this.prev = prev;
            this.current = current;
        }
        @Override
        public void run() {
            int count = 10;
            while (count > 0) {
                synchronized (prev) {

                    synchronized (current) {
                        Log.i(TAG, name);
                        count --;
                        current.notify();
                    }

                    try {
                        prev.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }

    public void startThread2() {
        Thread ta = new Thread(new PrintRunnable("A", oc, oa));
        Thread tb = new Thread(new PrintRunnable("B", oa, ob));
        Thread tc = new Thread(new PrintRunnable("C", ob, oc));
        try {
            ta.start();
            Thread.sleep(100);
            tb.start();
            Thread.sleep(100);
            tc.start();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

wait()会释放对象锁;notify()是起到唤醒等待对象锁的线程的作用,并不会马上释放锁,但是一旦同步代码块执行完毕后,就会释放对象锁。

2.生产者-消费者问题

代码如下:

 /**
     * 生产者消费者问题
     */
    private static final int MAX_COUNT = 10;
    List<String> product = new LinkedList<>();

    // 生产者
    private Runnable build = new Runnable() {
        @Override
        public void run() {
            while (true) {
                synchronized (product) {
                    while (product.size() >= MAX_COUNT) {
                        // 如果商品已经达到最大存储量,则暂时不生产
                        try {
                            Log.i(TAG, Thread.currentThread().getName() + " 仓库已满");
                            product.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    product.add("商品");
                    Log.i(TAG, Thread.currentThread().getName() + " 生产一个商品,当前商品存储量:" + product.size());
                    product.notifyAll(); // 唤醒等待商品的消费者
                }
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    };

    // 消费者
    private Runnable consume = new Runnable() {
        @Override
        public void run() {
            while (true) {
                synchronized (product) {
                    while (product.isEmpty()) {
                        try {
                            Log.i(TAG, Thread.currentThread().getName() + " 仓库已空");
                            product.wait(); // 没有商品消费,等待生产
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    product.remove(0);
                    Log.i(TAG, Thread.currentThread().getName() + " 消费一个商品,当前商品存储量:" + product.size());
                    product.notifyAll(); // 通知等待生产的生产者
                }
                try {
                    Thread.sleep(4000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    };

    public void startThread3() {
        Thread buildThread1 = new Thread(build);
        Thread buildThread2 = new Thread(build);
        Thread consumeThread1 = new Thread(consume);
        Thread consumeThread2 = new Thread(consume);
        Thread consumeThread3 = new Thread(consume);
        buildThread1.start();
        consumeThread1.start();
        buildThread2.start();
        consumeThread2.start();
        consumeThread3.start();
    }

打印如下:
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1476573.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Tomcat架构分析

Tomcat的核心组件 Tomcat将请求器和处理器分离&#xff0c;使用多种请求器支持不同的网络协议&#xff0c;而处理器只有一个。从而网络协议和容器解耦。 Tomcat的容器 Host&#xff1a;Tomcat提供多个域名的服务&#xff0c;其将每个域名都视为一个虚拟的主机&#xff0c;在…

面试笔记系列四之SpringBoot+SpringCloud基础知识点整理及常见面试题

什么是 Spring Boot&#xff1f; Spring Boot 是 Spring 开源组织下的子项目&#xff0c;是 Spring 组件一站式解决方案&#xff0c;主要是简化了使用 Spring 的难度&#xff0c;简省了繁重的配置&#xff0c;提供了各种启动器&#xff0c;开发者能快速上手。 Spring Boot 有哪…

Stable-Diffusion ubuntu服务器部署,报错解决方法(小白教程)

Stable Diffusion是一个深度学习模型&#xff0c;专注于生成高质量的图像。它由CompVis团队与Stability AI合作开发&#xff0c;并在2022年公开发布。这个模型使用文本提示&#xff08;text prompts&#xff09;生成详细、逼真的图像&#xff0c;是目前人工智能图像生成领域的一…

浅谈 Linux 网络编程 socket

文章目录 socket 介绍 socket 介绍 socket 被翻译成 网络套接字&#xff0c;这个名字实在是不好理解&#xff0c;我更愿意称为"插槽"。 忽略 socket 的中文名&#xff0c;先无脑记住两个规则&#xff1a; ① 记住&#xff0c;一个文件描述符(fd) 指向一个 socket&…

队列的概念及使用

目录 一. 概念 二. 队列的使用 三. 队列模拟实现 四. 循环队列 五. 面试题 一. 概念 队列 &#xff1a;只允许在一端进行插入数据操作&#xff0c;在另一端进行删除数据操作的特殊线性表&#xff0c;队列具有先进先出 FIFO(First In First Out) 入队列&#xff1a;进行插入操…

xss过waf的小姿势

今天看大佬的视频学到了几个操作 首先是拆分发可以用self将被过滤的函数进行拆分 如下图我用self将alert拆分成两段依然成功执行 然后学习另一种姿势 <svg id"YWxlcnQoIlhTUyIp"><img src1 οnerrοr"window[eval](atob(document.getElementsByTagNa…

【低代码开发_RuoYi_框架】RuoYi框架_前端页面部署/搭建

开源软件的影响力 随着信息技术的快速发展&#xff0c;开源软件已经成为软件开发的趋势&#xff0c;并产生了深远的影响。开源软件的低成本、可协作性和透明度等特点&#xff0c;使得越来越多的企业和个人选择使用开源软件&#xff0c;促进了软件行业的繁荣。然而&#xff0c;…

vue2+elementui上传照片(el-upload 超简单)

文章目录 element上传附件&#xff08;el-upload 超详细&#xff09;代码展示html代码data中methods中接口写法 总结 element上传附件&#xff08;el-upload 超详细&#xff09; 这个功能其实比较常见的功能&#xff0c;后台管理系统基本上都有&#xff0c;这就离不开element的…

华为OD技术面试案例3-2024年

技术一面&#xff1a; 1.手撕代码&#xff0c;算法题&#xff1a; 【最小路径和】 手撕代码通过&#xff0c;面试官拍了照片 2.深挖项目&#xff0c;做过的自认为最好的一个项目&#xff0c;描述做过的项目的工作过程&#xff0c;使用到哪些技术&#xff1f; 技术二面&…

高压高能碳陶瓷无感电阻的制作以及应用?

由于现有需求&#xff0c;许多现代电子电路和设备都会经历瞬态脉冲和浪涌。这反过来又导致需要“设计”瞬态浪涌保护&#xff0c;尤其是在电机控制器等电路中。当电机启动时&#xff0c;此时消耗的电流过大&#xff0c;可能导致电阻器故障。同样&#xff0c;如果电容器用于电机…

【MySQL】基于Docker搭建MySQL一主二从集群

本文记录了搭建mysql一主二从集群&#xff0c;这样的一个集群master为可读写&#xff0c;slave为只读。过程中使用了docker&#xff0c;便于快速搭建单体mysql。 1&#xff0c;准备docker docker的安装可以参考之前基于yum安装docker的文章[1]。 容器相关命令[2]。 查看正在…

加密与安全_探索常用编码算法

文章目录 概述什么是编码编码分类ASCII码 &#xff08;最多只能有128个字符&#xff09;Unicode &#xff08;用于表示世界上几乎所有的文字和符号&#xff09;URL编码 &#xff08;解决服务器只能识别ASCII字符的问题&#xff09;实现&#xff1a;编码_URLEncoder实现&#xf…

机器人内部传感器阅读梳理及心得-速度传感器-模拟式速度传感器

速度传感器是机器人内部传感器之一&#xff0c;是闭环控制系统中不可缺少的重要组成部分&#xff0c;它用来测量机器人关节的运动速度。可以进行速度测量的传感器很多&#xff0c;如进行位置测量的传感器大多可同时获得速度的信息。但是应用最广泛、能直接得到代表转速的电压且…

【大数据架构(2)】kappa架构介绍

文章目录 一. Kappa架构1. Speed Layer (Stream Layer) - The Foundation of Kappa Architecture2. Stream Processing: The Heart of Kappa Architecture 二. Benefits of Kappa and Streaming Architecture1. Simplicity and Streamlined Pipeline2. High-Throughput Process…

4_相机透镜畸变

理论上讲&#xff0c;是可能定义一种透镜而不引入任何畸变的。然而现实世界没有完美的透镜。这主要是制造上的原因&#xff0c;因为制作一个“球形”透镜比制作一个数学上理想的透镜更容易。而且从机械方面也很难把透镜和成像仪保持平行。下面主要描述两种主要的透镜畸变并为他…

[vscode] 1. 在编辑器的标签页下显示文件目录(标签页显示面包屑) 2. 在标题栏上显示当前文件的完整路径

1. 标签页显示面包屑 view->Appearance->Breadcrumbs 2. 在标题栏上显示当前文件的完整路径 搜索 window.title将原来的值activeEditorShort 修改为 activeEditorMedium 参考&#xff1a; vscode在编辑器的标签页下显示文件目录&#xff08;标签页显示面包屑&#xf…

Laravel - API 项目适用的图片验证码

1. 安装 gregwar/captcha 图片验证码接口的流程是&#xff1a; 生成图片验证码 生成随机的 key&#xff0c;将验证码文本存入缓存。 返回随机的 key&#xff0c;以及验证码图片 # 不限于 laravel 普通 php 项目也可以使用额 $ composer require gregwar/captcha2. 开发接口 …

尚硅谷(SpringCloudAlibaba微服务分布式)学习代码Eureka部分

1.项目结构 2.cloud2024 pom <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation"http://maven.a…

.NET生成MongoDB中的主键ObjectId

前言 因为很多场景下我们需要在创建MongoDB数据的时候提前生成好主键为了返回或者通过主键查询创建的业务&#xff0c;像EF中我们可以生成Guid来&#xff0c;本来想着要不要实现一套MongoDB中ObjectId的&#xff0c;结果发现网上各种各样的实现都有&#xff0c;不过好在阅读C#…

Vue的生命周期函数

今天我们来讲一讲Vue中的生命周期函数 每个Vue实例在其生命周期中都会经历多个关键阶段&#xff0c;这些阶段包括数据监听设置、模板编译、实例DOM挂载以及数据变化时的DOM更新等。同时&#xff0c;Vue提供了一系列生命周期钩子函数&#xff0c;允许开发者在这些重要阶段插入自…