Java并发-交替打印的四种方法。

news2024/12/29 11:39:27

1 前言

如下图所示,现在有两个线程A,B;A打印12345,B打印abcde,结果为1a2b3c4d5e交替输出。

1.1 采用wait和notify

【分析】我们要求线程A始终先打印,因此在线程B先获得CPU使用时间时也应该阻塞。

 细节

  • 线程A应该打印后,先notify,然后wait;
  • 线程B先阻塞,然后打印后,先notity,再wait。
  • 其线程B先阻塞的方法,采用countdownlatch实现
  • 线程A在for循环后还需要在进行notify,因为线程B最后才能被打印。因此最后一定被阻塞。
package cn.itcast.n6.c1;


import java.util.concurrent.CountDownLatch;

/**
 * @author : msf
 * @date : 2022/12/2
 * 交替输出
 */
public class AlteratePrint2 {
    public static void main(String[] args) {
        String numberA = "123456";
        String characterB = "abcdef";
        Object lock = new Object();
        CountDownLatch latch = new CountDownLatch(1);

        Thread threadA = new Thread(() -> {
            synchronized (lock) {
                for (char c : numberA.toCharArray()) {
                    System.out.print(c);
                    try {
                        // 唤醒线程b
                        latch.countDown();
                        lock.notify();
                        // 线程A阻塞
                        lock.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                // 是为了更好的退出,因为程序在结束时候肯定会有一个线程在阻塞住。
                lock.notify();
            }
        });

        Thread threadB = new Thread(() -> {
            try {
                latch.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            synchronized (lock) {
                for (char c : characterB.toCharArray()) {
                    try {

                        System.out.print(c);
                        lock.notify();
                        lock.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                }
            }

        });

        threadB.start();
        threadA.start();
    }
}

上述代码结果如下:

1.2 采用park 和unpark

package cn.itcast.n6.c1;

import java.util.concurrent.locks.LockSupport;

/**
 * @author : msf
 * @date : 2022/12/2
 * 交替输出
 */
public class AlteratePrint {
    static Thread threadA = null;
    static Thread threadB = null;
    public static void main(String[] args) {
        String numberA = "123456";
        String characterB = "abcdef";

        threadA = new Thread(()->{
            for (char c : numberA.toCharArray()) {
                System.out.print(c);
                LockSupport.unpark(threadB);
                LockSupport.park();

            }
        });
        threadB = new Thread(()->{
            for (char c : characterB.toCharArray()) {
                LockSupport.park();
                System.out.print(c);
                LockSupport.unpark(threadA);
            }
        });
        threadA.start();
        threadB.start();
    }
}

上述代码结果如下:

1.3 采用lock锁和condition

package cn.itcast.n6.c1;


import java.util.concurrent.CountDownLatch;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @author : msf
 * @date : 2022/12/2
 * 交替输出
 */
public class AlteratePrint3 {
    public static void main(String[] args) {
        String numberA = "123456";
        String characterB = "abcdef";
        ReentrantLock lock = new ReentrantLock();
        Condition conditionA = lock.newCondition();
        Condition conditionB = lock.newCondition();
        CountDownLatch latch = new CountDownLatch(1);

        Thread threadA = new Thread(() -> {
            lock.lock();
            try {
                for (char c : numberA.toCharArray()) {
                    System.out.print(c);
                    try {
                        // 唤醒线程b
                        latch.countDown();
                        conditionB.signal();
                        // 线程A阻塞
                        conditionA.await();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                conditionB.signal();
            } finally {
                lock.unlock();

            }

        });

        Thread threadB = new Thread(() -> {
            try {
                latch.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            lock.lock();
            try {
                for (char c : characterB.toCharArray()) {
                    try {

                        System.out.print(c);
                        // 唤醒线程a
                        conditionA.signal();
                        // 线程b阻塞
                        conditionB.await();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            } finally {
                lock.unlock();
            }

        });


        threadB.start();
        threadA.start();
    }
}

上述代码结果如下:

1.4 采用transferQueue实现

为什么可以用transferQueue实现呢?

原因

其的take 和 transfer命令都是同步阻塞的。

package cn.itcast.n6.c1;


import java.util.concurrent.CountDownLatch;
import java.util.concurrent.LinkedTransferQueue;
import java.util.concurrent.TransferQueue;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @author : msf
 * @date : 2022/12/2
 * 交替输出
 */
public class AlteratePrint4 {
    public static void main(String[] args) {
        String numberA = "123456";
        String characterB = "abcdef";
        TransferQueue<Character> queue = new LinkedTransferQueue<>();

        Thread threadA = new Thread(() -> {
            try {
                for (char c : numberA.toCharArray()) {
                    queue.transfer(c);
                    System.out.print(queue.take());
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });

        Thread threadB = new Thread(() -> {
            try {
                for (char c : characterB.toCharArray()) {
                    System.out.print(queue.take());
                    queue.transfer(c);
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        threadB.start();
        threadA.start();
    }
}

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

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

相关文章

【人工智能/算法】搜索求解(Solving Problemsby Searching)

文章目录一、求解与搜索二、盲目式搜索1. 深度优先搜索&#xff08;Depth First Search, DFS&#xff09;回溯搜索&#xff08;Backtracking Search&#xff09;2. 广度优先搜索&#xff08;Breadth First Search, BFS&#xff09;一致代价搜索&#xff08;Uniform-cost Search…

TLog轻量级分布式日志标记追踪神器

文章目录TLog简介项目特性安装TLogspringboot依赖spring native依赖日志框架适配方式(举例Log4j框架适配器)任务框架支持(举例XXL-JOB框架)TLog架构图TLog简介 TLog通过对日志打标签完成企业级微服务的日志追踪。它不收集日志&#xff0c;使用简单&#xff0c; 产生全局唯一的…

Actor 生命周期

一&#xff0c;一览图 二&#xff0c; 大致流程 三&#xff0c;细节 从磁盘加载 已位于关卡中的 Actor 使用此路径&#xff0c;如 LoadMap 发生时、或 AddToWorld&#xff08;从流关卡或子关卡&#xff09;被调用时。 包/关卡中的 Actor 从磁盘中进行加载。 PostLoad - 在序…

支持向量机(SVM)—— 详细推导及案例应用可视化

支持向量机&#xff08;SVM&#xff09; 1. 什么是支持向量机&#xff1f; 在上图中&#xff0c;我们想在二维平面中通过画出一条分界线将黑点与白点分开&#xff0c;很明显&#xff0c;我们认为在上面所画的三条分界线中H3H_3H3​是最好的&#xff0c;因为H1H_1H1​压根就没有…

【行为识别】差影法三维人体姿态行为识别【含Matlab源码 277期】

⛄一、简介 该课题为基于MATLAB差影法的人体姿态识别。需要准备对应的模板图片作为背景图&#xff0c;然后测试图和背景图进行作差&#xff0c;结合形态学知识&#xff0c;提取出人体轮廓&#xff0c;接上最外接矩形&#xff0c;得出矩形长宽&#xff0c;计算长宽比例&#xf…

江江文具店铺运营方案设计

目 录 摘 要 I ABSTRACT II 第一章 项目背景 1 1.1电子商务基本概念 1 1.2电子商务现状及发展趋势 1 1.3文具行业的发展现状 2 第二章 文具行业介绍 4 2.1文具行业的调查与分析 4 2.1.1文具行业电子商务渗透率 4 2.1.2文具行业内企业电子商务销售平台使用状况调查统计 5 2.1.3文…

自研芯片重构云上算力革新,满足用户所有负载的需求!

目前&#xff0c;云计算已深入到整个云基础设施&#xff0c;进入硬件协同创新的“深水区”&#xff0c;芯片创新之路是最底层的创新&#xff0c;是最具颠覆性的&#xff0c;也是改变云计算游戏规则的能力。 而亚马逊云科技硬件创新背后的初衷&#xff1a;为云而生的硬件设计&am…

【计算机毕业设计】71.大学生兼职信息系统源码

一、系统截图&#xff08;需要演示视频可以私聊&#xff09; 摘 要 21世纪的今天&#xff0c;随着社会的不断发展与进步&#xff0c;人们对于信息科学化的认识&#xff0c;已由低层次向高层次发展&#xff0c;由原来的感性认识向理性认识提高&#xff0c;管理工作的重要性已逐…

react源码中的协调与调度

requestEventTime 其实在React执行过程中&#xff0c;会有数不清的任务要去执行&#xff0c;但是他们会有一个优先级的判定&#xff0c;假如两个事件的优先级一样&#xff0c;那么React是怎么去判定他们两谁先执行呢&#xff1f; // packages/react-reconciler/src/ReactFibe…

数字化门店| 运动场馆管理系统| 智慧门店小程序

忙碌了一天或闲暇之余想要放松&#xff0c;不少年轻人都会选择前往运动场馆进行各种运动&#xff0c;如打篮球、踢足球、打羽毛球等&#xff0c;一些城市的某个特定区域内聚集着不同品牌的运动场馆&#xff0c;相互之间竞争激烈。 如今&#xff0c;消费升级下&#xff0c;消费者…

Win10系统修改用户名以及C盘下Users用户名实操手册(实测有效)

当然&#xff0c;前提先说下如无必要&#xff0c;不建议修改C盘user下用户名&#xff0c;毕竟重装系统可能就在那一瞬间。我们要理解里面的原理&#xff0c;逻辑关系就会好操作很多了。再次申明&#xff0c;目前这只是针对Win10的实操&#xff0c;Win11的操作会有一些不同&…

铁矿行业商业智能BI经营分析框架(三)财务能力分析

铁矿行业属于黑色金属矿采选业&#xff0c;商业智能BI对于这个行业的财务能力指标分析框架跟其它行业大体上是一样的。比如从盈利能力、债务风险、营运能力、发展能力、现金流这几个角度去看。 财务分析 - 派可数据商业智能BI可视化分析平台 一、盈利能力 商业智能BI从资产、…

天黑了、让我为你关窗帘吧

今天遇到朋友发来的一个需求&#xff0c;需要做一个窗户上下拉窗帘的小小的交互&#xff0c;于是就有了今天的小DEMO&#xff0c;要实现下图一个效果&#xff0c;需要开窗帘&#xff0c;关窗帘&#xff0c;中途还可以暂停&#xff0c;就这样一个小小的效果&#xff0c;我们来分…

阿里18年架构师,带你分析经典算法应用思路,探究分布式背后原理

你要知道 长期以来,在996的工作压力下&#xff0c;工程师们更重视实践中的技巧&#xff0c;力求快速解决眼前的问题,而鲜有时间关注问题背后的底层原理。 表面看来&#xff0c;这种做法提高了工作效率&#xff0c;但实际上&#xff0c;这样容易形成“头疼医头&#xff0c;脚疼…

【Python】解决CNN中训练权重参数不匹配size mismatch for fc.weight,size mismatch for fc.bias

目录 1.问题描述 2.问题原因 3.问题解决 3.1思路1——忽视最后一层权重 额外说明&#xff1a;假如载入权重不写strictFalse, 直接是model.load_state_dict(pre_weights, strictFalse)&#xff0c;会报错找不到key&#xff1f; 解决办法是&#xff1a;加上strictFalse&…

Ajax学习:解决跨域_JSONP

JSONP&#xff1a;非官方的跨域解决方案,纯粹依靠程序员的聪明才智&#xff0c;只支持get请求 JSONP是怎么工作的&#xff1a;再页面中有一些标签天生具有跨域能力&#xff0c;就像是link,img,iframe,script JSONP就是利用script标签的跨域能力来发送请求 如下所示&#xff1a…

[附源码]计算机毕业设计毕业生就业管理系统Springboot程序

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

【Docker】Docker常用命令(包含Dockerfile指令)

目录一.Docker常用命令1.帮助命令2.镜像命令3.容器命令4.其他常用命令5.更多更详细命令二.Dockerfile常用指令1.常用指令2.CMD 和 ENTRYPOINT 的区别一.Docker常用命令 1.帮助命令 # docker version //查看docker版本号 # docker info //查看docker的系统信息…

外贸员的日常工作分享

外贸人米贸搜的日常工作流程为你整理如下。希望能帮到你: 外贸业务员的职责 一、业务人员在向国外买家询价前&#xff0c;要了解客户的基本信息&#xff0c;包括是否是终端客户&#xff0c;年采购量&#xff0c;消费区域&#xff0c;产品的用途&#xff0c;规格&#xff0c;质…

(附源码)SSM座位管理系统 毕业设计 250858

基于SSM的座位管理系统 摘 要 21世纪时信息化的时代&#xff0c;几乎任何一个行业都离不开计算机&#xff0c;将计算机运用于学校的各种信息管理也是十分常见的。过去使用手工的管理方式对高校教室座位进行管理&#xff0c;造成了管理繁琐、难以维护等问题&#xff0c;如今使用…