利用多线程打印出1 2 3

阿里控股_爱橙科技_笔试

题目:利用多线程打印出1 2 3,请给出尽可能多的实现方案。


其中,悲观锁可以使用Synchronized、Reentrantlock实现,乐观锁可以使用AtomicInteger实现,底层是CAS实现乐观锁。Semaphore 是一种计数信号量,它用于控制同时访问特定资源或执行某个操作的线程数量。这里控制了一个许可来达到每个线程打印完再释放许可让下一个线程执行。Join方法循环要放在外面,每次都要创建三个线程来打印,每个线程通过等待前继线程执行完再执行来达到按顺序打印"123"的效果。

1、使用Join()实现

实现思路是:定义了一个内部类PrintTask实现自Runnable,每个线程负责打印一个特定的数字(1、2、或3)。在每个线程的run方法中,通过检查是否有前一个线程(preThread),如果有,则调用其join()方法等待前一个线程执行完毕,然后再打印自己的数字并循环。这样可以确保打印出的序列是按1、2、3的顺序进行。

package com.java.demo.Exam;public class AlibabaExam {public static void main(String[] args) throws InterruptedException {final int loopCount = 10; // 指定循环打印的次数for (int i = 0; i < loopCount; i++) {Thread thread1 = new Thread(new PrintTask(1, null));Thread thread2 = new Thread(new PrintTask(2, thread1));Thread thread3 = new Thread(new PrintTask(3, thread2));// 启动线程thread1.start();thread2.start();thread3.start();// 等待所有线程执行完毕thread1.join();thread2.join();thread3.join();}}static class PrintTask implements Runnable {private final int number;private final Thread prevThread;public PrintTask(int number, Thread prevThread) {this.number = number;this.prevThread = prevThread;}@Overridepublic void run() {if (prevThread != null) {try {// 等待前一个线程完成打印prevThread.join();} catch (InterruptedException e) {e.printStackTrace();}}System.out.print(number);}}
}

2、使用Synchronized实现

package com.java.demo.LeetCode;public class Print123BySynchronized {private static class PrintNumber {private int counter = 1; // 计数器,用于控制打印次数private final Object lock = new Object(); // 用于同步的锁对象public void print1() {for (int i = 0; i < 10; ) { // 控制总共打印10次synchronized (lock) {if (counter % 3 == 1) { // 当计数器模3等于1时,打印1System.out.print("1");counter++;i++; // 内部计数器加1,控制循环lock.notifyAll(); // 唤醒其他等待的线程} else {try {lock.wait(); // 不符合条件时,释放锁并等待} catch (InterruptedException e) {Thread.currentThread().interrupt();System.out.println("Thread interrupted.");}}}}}public void print2() {for (int i = 0; i < 10; ) {synchronized (lock) {if (counter % 3 == 2) {System.out.print("2");counter++;i++;lock.notifyAll();} else {try {lock.wait();} catch (InterruptedException e) {Thread.currentThread().interrupt();System.out.println("Thread interrupted.");}}}}}public void print3() {for (int i = 0; i < 10; ) {synchronized (lock) {if (counter % 3 == 0) {System.out.print("3");counter++;i++;lock.notifyAll();} else {try {lock.wait();} catch (InterruptedException e) {Thread.currentThread().interrupt();System.out.println("Thread interrupted.");}}}}}}public static void main(String[] args) {PrintNumber printNumber = new PrintNumber();Thread t1 = new Thread(printNumber::print1);Thread t2 = new Thread(printNumber::print2);Thread t3 = new Thread(printNumber::print3);t1.start();t2.start();t3.start();}
}

3、使用ReentrantLock的Condition来实现

package com.java.demo.LeetCode;import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;public class Print123ByReentrantLock {private static class PrintNumber {private int counter = 1; // 打印轮数计数器private final int totalPrints = 10; // 总共打印10次private final ReentrantLock lock = new ReentrantLock();private final Condition condition1 = lock.newCondition();private final Condition condition2 = lock.newCondition();private final Condition condition3 = lock.newCondition();public void print1() {for (int i = 0; i < totalPrints; i++) {lock.lock();try {while (counter % 3 != 1) {condition1.await(); // 等待直到应该打印1}System.out.print("1");counter++;condition2.signal(); // 通知打印2的线程} catch (InterruptedException e) {Thread.currentThread().interrupt();System.out.println("Thread interrupted.");} finally {lock.unlock();}}}public void print2() {for (int i = 0; i < totalPrints; i++) {lock.lock();try {while (counter % 3 != 2) {condition2.await(); // 等待直到应该打印2}System.out.print("2");counter++;condition3.signal(); // 通知打印3的线程} catch (InterruptedException e) {Thread.currentThread().interrupt();System.out.println("Thread interrupted.");} finally {lock.unlock();}}}public void print3() {for (int i = 0; i < totalPrints; i++) {lock.lock();try {while (counter % 3 != 0) {condition3.await(); // 等待直到应该打印3}System.out.print("3");counter++;condition1.signal(); // 循环回到打印1,通知打印1的线程} catch (InterruptedException e) {Thread.currentThread().interrupt();System.out.println("Thread interrupted.");} finally {lock.unlock();}}}}public static void main(String[] args) {PrintNumber printNumber = new PrintNumber();Thread t1 = new Thread(printNumber::print1);Thread t2 = new Thread(printNumber::print2);Thread t3 = new Thread(printNumber::print3);t1.start();t2.start();t3.start();}
}

4、使用Semaphore实现

package com.java.demo.LeetCode;import java.util.concurrent.Semaphore;public class Print123BySemaphore {private static final int PRINT_COUNT = 10; // 每个线程打印的次数// 创建三个信号量,初始状态只允许第一个线程运行private static final Semaphore semaphore1 = new Semaphore(1);private static final Semaphore semaphore2 = new Semaphore(0);private static final Semaphore semaphore3 = new Semaphore(0);public static void main(String[] args) {new Thread(new PrintTask(semaphore1, semaphore2, 1)).start();new Thread(new PrintTask(semaphore2, semaphore3, 2)).start();new Thread(new PrintTask(semaphore3, semaphore1, 3)).start();}static class PrintTask implements Runnable {private final Semaphore currentSemaphore;private final Semaphore nextSemaphore;private final int number;public PrintTask(Semaphore currentSemaphore, Semaphore nextSemaphore, int number) {this.currentSemaphore = currentSemaphore;this.nextSemaphore = nextSemaphore;this.number = number;}@Overridepublic void run() {for (int i = 0; i < PRINT_COUNT; i++) {try {currentSemaphore.acquire(); // 获取当前信号量System.out.print(number); // 打印数字nextSemaphore.release(); // 释放下一个信号量} catch (InterruptedException e) {Thread.currentThread().interrupt(); // 设置线程中断状态}}}}
}

5、使用AtomicInteger实现

package com.java.demo.LeetCode;import java.util.concurrent.atomic.AtomicInteger;public class Print123ByAtomicInteger {private static final int PRINT_COUNT = 10; // 每个线程打印的次数private static final int THREAD_COUNT = 3; // 线程数量private static final AtomicInteger current = new AtomicInteger(0); // 当前应当打印的线程索引public static void main(String[] args) {for (int i = 0; i < THREAD_COUNT; i++) {new Thread(new PrintTask(i)).start();}}static class PrintTask implements Runnable {private final int threadId;public PrintTask(int threadId) {this.threadId = threadId;}@Overridepublic void run() {for (int i = 0; i < PRINT_COUNT; i++) {while (true) {if (current.get() % THREAD_COUNT == threadId) {System.out.print(threadId + 1); // 打印当前线程的ID+1(打印1,2,3)current.incrementAndGet(); // 当前线程索引加1break;}}}}}
}

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

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

相关文章

spring管理bean

大家好&#xff0c;这里是教授.F 管理bean方面&#xff1a; 获取bean: /** * 通过类型来获取容器的 bean 对象 */ Test public void getMonsterByType() {ApplicationContext ioc new ClassPathXmlApplicationContext("beans.xml");Monster monster ioc.getBean(…

Flutter开发效率提升1000%,Flutter Quick教程之定义Api(四)

现在我们来讲讲&#xff0c;如何建立Api 响应数据的变量。 这个变量&#xff0c;本质上就是对根据json数据生成model的引用。 这个name就是引用名。 这个path&#xff0c;就是引用的Model Data里面的具体字段&#xff0c;在实际操作过程中&#xff0c;校验是由右边的json数据…

从运维故障中你都学到了什么?

一阵急促尖锐的铃声响起&#xff0c;王一搏忐忑不安地接起电话&#xff0c;被告知系统有20台服务器批量重启。 20 台&#xff01;批量重启&#xff01;意识到问题的严重性&#xff0c;王一搏迅速调整好状态&#xff0c;准备投身一场激烈的救火工作中。 然而事件的走向却远远超…

JVM的内存结构

JVM 内存结构 方法区: 方法区主要用于存储虚拟机加载的类信息、常量、静态变量&#xff0c;以及编译器编译后的代码等数据。 程序计数器 由于在JVM中&#xff0c;多线程是通过线程轮流切换来获得CPU执行时间的&#xff0c;因此&#xff0c;在任一具体时刻&#xff0c;一个CP…

kali配置静态ip

kali配置静态ip 因为一些环境需要&#xff0c;本地linux主机需要搭建一个桥接模式的网络&#xff0c;那么直接就在kali中配置了&#xff0c; 打开vim /etc/network/interfaces 这里就需要自己配置一下ip&#xff0c;网关&#xff0c;路由等内容 这里参考&#xff1a;参考链接 …

排序方法——《选择排序》

P. S.&#xff1a;以下代码均在VS2019环境下测试&#xff0c;不代表所有编译器均可通过。 P. S.&#xff1a;测试代码均未展示头文件stdio.h的声明&#xff0c;使用时请自行添加。 博主主页&#xff1a;Yan. yan.                        …

关于文件上传失败问题的排查思路

问题场景&#xff1a; 最近公司的app有很多用户反馈上传文件失败了。业务路径就是简单的app前端调用后端文件上传接口&#xff0c;所以发生上传失败的可能因素可能是&#xff1a;1、文件大小/文件类型等是否有问题&#xff0c;公司用的是七牛的文件服务器&#xff0c;对文件上…

我成功创建了一个Electron应用程序

1.创建electron项目命令&#xff1a; npm create quick-start/electron electron-memo 2选择&#xff1a;√ Select a framework: vue √ Add TypeScript? ... No √ Add Electron updater plugin? ... Yes √ Enable Electron download mirror proxy? ... Yes 3.命令&am…

保护关键业务资产的四个步骤

提到 “关键资产 ”&#xff0c;相信大家并不陌生&#xff0c;它是企业 IT 基础设施中对组织运作至关重要的技术资产。如果这些资产&#xff08;如应用服务器、数据库或特权身份&#xff09;出现问题&#xff0c;势必会对企业安全态势造成严重影响。 但每项技术资产都被视为关…

IT项目常用考核指标

在IT项目管理中&#xff0c;考核指标是用来评估项目进展和成果的重要依据。以下是一些常用的IT项目考核指标&#xff0c;包括具体的指标名称、计算公式、基准达标值以及常见问题&#xff1a; 1 项目进度准时率 项目的生命线是什么&#xff1f;没错&#xff0c;是时间&#xf…

【UML用户指南】-01-UML基本元素的介绍(一)

目录 1、UML的词汇表 2、UML的4种事物 2.1、结构事物 1&#xff09;类 2&#xff09;接口 3&#xff09;协作 4&#xff09;用例&#xff08;use case&#xff09; 5&#xff09;主动类&#xff08;active class&#xff09; 6&#xff09;构件&#xff08;component&a…

揭秘c语言储存类别

前言 欢迎来到我的博客 个人主页:北岭敲键盘的荒漠猫-CSDN博客 本文将整理c语言的储存类型的知识点 储存类型概念 描述:用于解决内存开辟与解放的时间的问题。跟作用域没啥关系。 但是呢&#xff0c;他也是能影响到程序的运行的&#xff0c;所以是很关键的。 类型: auto :自…

拉取代码编辑器中报错`Delete ␍ prettier/prettier` 问题的解决方案

当您在使用 git clone 下载Web前端代码仓库后&#xff0c;可能会遇到 Delete ␍ prettier/prettier 的提示时&#xff0c;这通常意味着您的代码中存在不兼容的换行符问题。 问题产生的原因 在不同的操作系统中&#xff0c;文本文件的换行符是不同的。Windows系统通常使用回车…

Pytorch常用函数用法归纳:Tensor张量之间的计算

1.torch.add() (1)函数原型: torch.add(input, other, alpha, out) (2)参数说明: 参数名称参数类型参数说明inputtorch.Tensor表示参与运算的第一个输入Tensor张量othertorch.Tensor或者Number表示参与运算的第二个输入Tensor张量或标量alphaNumber, optional一个可选的缩放…

idea mac快捷键

Mac快捷键 快捷键 说明 ⌘ F 在当前窗口查找 ⌘ ⇧ F 在全工程查找 ⌘ ⇧ ⌥ N 查找类中的方法或变量 F3 / ⇧ F3 移动到搜索结果的下/上一匹配处 ⌘ R 在当前窗口替换 ⌘ ⇧ R 在全工程替换 ⌘ ⇧ V 可以将最近使用的剪贴板内容选择插入到文本 ⌥…

负压实验室设计建设方案

随着全球公共卫生事件的频发&#xff0c;负压实验室的设计和建设在医疗机构中的重要性日益凸显。负压实验室&#xff0c;特别是负压隔离病房&#xff0c;主要用于控制传染性疾病的扩散&#xff0c;保护医护人员和周围环境的安全。广州实验室装修公司中壹联凭借丰富的实验室装修…

MQTT.FX的使用

背景 在如今物联网的时代下&#xff0c;诞生了许多的物联网产品&#xff0c;这些产品通过BLE、WIFI、4G等各种各样的通信方式讲数据传输到各种各样的平台。 除了各个公司私有的云平台外&#xff0c;更多的初学者会接触到腾讯云、阿里云之类的平台。设备接入方式也有着多种多样…

神经网络应用场景——图像识别

神经网络在图像识别中的应用是一项重要且广泛的技术&#xff0c;下面将详细解释和说明神经网络在图像识别中的定义、特点以及应用场景。 一、定义 神经网络在图像识别中的应用&#xff0c;主要是指利用神经网络模型对图像进行特征提取和分类&#xff0c;从而实现对图像中物体…

Spring自带定时任务@Scheduled注解

文章目录 1. cron表达式生成器2. 简单定时任务代码示例&#xff1a;每隔两秒打印一次字符3. Scheduled注解的参数3.1 cron3.2 fixedDelay3.3 fixedRate3.4 initialDelay3.5 fixedDelayString、fixedRateString、initialDelayString等是String类型&#xff0c;支持占位符3.6 tim…

2004NOIP普及组真题 4. 火星人

线上OJ&#xff1a; 【04NOIP普及组】火星人 核心思想&#xff1a; 本题的难点是阅读理解。通读后发现&#xff0c;题目的本质是全排列&#xff0c;加上的数字 m &#xff0c;起始就是调用 m 次 next_permutation() 。 题解代码&#xff1a; #include <bits/stdc.h> u…