当前位置: 首页 > news >正文

1195. 交替打印字符串

1195. 交替打印字符串

题目描述

编写一个可以从 1 到 n 输出代表这个数字的字符串的程序,但是:

  • 如果这个数字可以被 3 整除,输出 "fizz"。
  • 如果这个数字可以被 5 整除,输出 "buzz"。
  • 如果这个数字可以同时被 3 和 5 整除,输出 "fizzbuzz"。

例如,当 n = 15,输出: 1, 2, fizz, 4, buzz, fizz, 7, 8, fizz, buzz, 11, fizz, 13, 14, fizzbuzz

假设有这么一个类:

class FizzBuzz {
  public FizzBuzz(int n) { ... }               // constructorpublic void fizz(printFizz) { ... }          // only output "fizz"public void buzz(printBuzz) { ... }          // only output "buzz"public void fizzbuzz(printFizzBuzz) { ... }  // only output "fizzbuzz"public void number(printNumber) { ... }      // only output the numbers
}

请你实现一个有四个线程的多线程版  FizzBuzz, 同一个 FizzBuzz 实例会被如下四个线程使用:

  1. 线程A将调用 fizz() 来判断是否能被 3 整除,如果可以,则输出 fizz
  2. 线程B将调用 buzz() 来判断是否能被 5 整除,如果可以,则输出 buzz
  3. 线程C将调用 fizzbuzz() 来判断是否同时能被 3 和 5 整除,如果可以,则输出 fizzbuzz
  4. 线程D将调用 number() 来实现输出既不能被 3 整除也不能被 5 整除的数字。

 

提示:

  • 本题已经提供了打印字符串的相关方法,如 printFizz() 等,具体方法名请参考答题模板中的注释部分。

 

解法

Java

class FizzBuzz {private int n;private int current = 1;public FizzBuzz(int n) {this.n = n;}// printFizz.run() outputs "fizz".public void fizz(Runnable printFizz) throws InterruptedException {while (current <= n) {synchronized (this) {if (current % 3 == 0 && current % 5 != 0) {if (current <= n) {printFizz.run();current++;notifyAll();}} else {wait();}}}}// printBuzz.run() outputs "buzz".public void buzz(Runnable printBuzz) throws InterruptedException {while (current <= n) {synchronized (this) {if (current % 5 == 0 && current % 3 != 0) {if (current <= n) {printBuzz.run();current++;notifyAll();}} else {wait();}}}}// printFizzBuzz.run() outputs "fizzbuzz".public void fizzbuzz(Runnable printFizzBuzz) throws InterruptedException {while (current <= n) {synchronized (this) {if (current % 15 == 0) {if (current <= n) {printFizzBuzz.run();current++;notifyAll();}} else {wait();}}}}// printNumber.accept(x) outputs "x", where x is an integer.public void number(java.util.function.IntConsumer printNumber) throws InterruptedException {while (current <= n) {synchronized (this) {if (current % 3 != 0 && current % 5 != 0) {if (current <= n) {printNumber.accept(current);current++;notifyAll();}} else {wait();}}}}
}

Java

关于"唤醒所有线程以便退出"这个操作,分析如下:

是否必须取决于具体实现

  • 不是绝对必须的:当 current > n 时,理论上各线程应该已经在各自的 while(current <= n) 循环中自然退出

  • 建议保留的原因

    1. 确保及时退出:避免某些线程长时间处于 await() 状态
    2. 防止内存泄漏:确保所有线程都能正常结束,释放资源
    3. 提高健壮性:即使主流程出现异常,也能保证线程正常终止

替代方案

如果不使用 signalAll(),也可以采用以下方式:

private void signalNext() {if (current > n) {return; // 直接返回,让各线程自然退出} else if (current % 15 == 0) {fizzbuzzCondition.signal();} else if (current % 3 == 0) {fizzCondition.signal();} else if (current % 5 == 0) {buzzCondition.signal();} else {numberCondition.signal();}
}

结论

虽然不是严格必需,但添加 signalAll() 是一种良好的编程实践,能确保程序更可靠地退出。

class FizzBuzz {private int n;private int current = 1;private final Lock lock = new ReentrantLock();private final Condition fizzCondition = lock.newCondition();private final Condition buzzCondition = lock.newCondition();private final Condition fizzbuzzCondition = lock.newCondition();private final Condition numberCondition = lock.newCondition();public FizzBuzz(int n) {this.n = n;}public void fizz(Runnable printFizz) throws InterruptedException {lock.lock();try {while (current <= n) {if (current % 3 == 0 && current % 5 != 0) {printFizz.run();current++;signalNext();} else {fizzCondition.await();}}} finally {lock.unlock();}}public void buzz(Runnable printBuzz) throws InterruptedException {lock.lock();try {while (current <= n) {if (current % 5 == 0 && current % 3 != 0) {printBuzz.run();current++;signalNext();} else {buzzCondition.await();}}} finally {lock.unlock();}}public void fizzbuzz(Runnable printFizzBuzz) throws InterruptedException {lock.lock();try {while (current <= n) {if (current % 15 == 0) {printFizzBuzz.run();current++;signalNext();} else {fizzbuzzCondition.await();}}} finally {lock.unlock();}}public void number(IntConsumer printNumber) throws InterruptedException {lock.lock();try {while (current <= n) {if (current % 3 != 0 && current % 5 != 0) {printNumber.accept(current);current++;signalNext();} else {numberCondition.await();}}} finally {lock.unlock();}}private void signalNext() {if (current > n) {// 唤醒所有线程以便退出fizzCondition.signalAll();buzzCondition.signalAll();fizzbuzzCondition.signalAll();numberCondition.signalAll();} else if (current % 15 == 0) {fizzbuzzCondition.signal();} else if (current % 3 == 0) {fizzCondition.signal();} else if (current % 5 == 0) {buzzCondition.signal();} else {numberCondition.signal();}}
}
http://www.jsqmd.com/news/24501/

相关文章:

  • gdb调试常用命令
  • 企业微信ipad协议实现聚合聊天系统、RPA机器人智能回复
  • 2025年市面上别墅石材品牌与行业内别墅石材源头厂家推荐榜单及口碑好的别墅石材产品分析
  • 最近公共祖先 (LCA)
  • ChatGPT API集成测试自动化框架的实践与成效汇报
  • [题解]【MX-S8】梦熊 CSP-S 2025 模拟赛
  • 2025四川碳晶板品牌
  • 详细介绍:求余运算和数学模运算的知识了解
  • 基于蚁群算法解决车辆路径问题(VRP)的MATLAB实现
  • 2025 年工业除湿机,恒温恒湿机,精密空调,除湿加湿一体机厂家最新推荐,产能、专利、环保三维数据透视
  • 从手动到全自动:我们如何用Dify重构了API回归测试流程
  • 2025 年管道除湿机,中央除湿机,新风除湿机,变频除湿机厂家最新推荐,产能、专利、环保三维数据透视
  • 2025年10月中国管理咨询公司推荐榜:五强数据对比
  • 条码识别插件 quaggaJS - microsoft
  • 2025年10月中国管理咨询公司推荐榜:金蓝盟领衔六强对比评测
  • 基于3GPP LTE标准的信道仿真模型
  • 2025 年灵巧手厂家最新推荐榜,技术实力与市场口碑深度解析,筛选高适配性与长耐用性优质品牌
  • Dify工作流实战:一键自动生成测试报告并推送钉钉,我每天白赚1小时
  • CF2043D Problem about GCD
  • 2025年10月智能工厂规划咨询公司排行:五家对比一目了然
  • 【2025-10-27】干就是了
  • 2025年10月智能工厂规划咨询公司推荐:客观评价榜及指标对比
  • 2025年10月智能工厂规划咨询公司推荐:热门对比榜五强深度解析
  • 2025 年 10 月 ups 发电机租赁,静音发电机租赁,发电机租赁附近,附近发电机租赁公司最新推荐,聚焦资质、案例、售后的五家机构深度解读
  • 2025 年 10 月 2 小时应急发电机租赁,山东发电机租赁,大型发电机租赁公司最新推荐,聚焦资质、案例、售后的五家机构深度解读
  • 2025年10月数字化咨询公司推荐:五强榜单与实战对比 .
  • 2025年10月精益制造咨询公司推荐榜:五强实测排行
  • 2025年10月精益制造咨询公司推荐:榜单揭晓与选型思路
  • 2025 年移动发电机租赁,大型发电机租赁,柴油发电机租赁公司最新推荐,聚焦资质、案例、售后的五家机构深度解读
  • 2025年10月绩效管理咨询公司推荐:五强榜单与选择指南