当前位置: 首页 > 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.hskmm.com/?act=detail&tid=40360

相关文章:

  • 回调函数
  • gdb调试常用命令
  • 2025年10月中国管理咨询公司推荐榜:五强数据对比
  • 条码识别插件 quaggaJS - microsoft
  • 2025 年灵巧手厂家最新推荐榜,技术实力与市场口碑深度解析,筛选高适配性与长耐用性优质品牌
  • Dify工作流实战:一键自动生成测试报告并推送钉钉,我每天白赚1小时
  • CF2043D Problem about GCD
  • 一起为可信数据流通添砖加瓦,隐语社区 OSCP 专项开源活动正式启动!
  • 2025年10月精益管理咨询公司推荐:权威榜单与多维对比评测
  • 2025年10月降本增效咨询公司推荐:实力榜对比五家优劣势
  • CF2093G Shorten the Array
  • 2025年10月降本增效咨询公司推荐榜:五强数据横评
  • 2025 年水处理聚丙烯酰胺,聚丙烯酰胺水处理剂,工业废水处理聚丙烯酰胺厂家最新推荐,产能、专利、环保三维数据透视!
  • 2025 年阴离子聚丙烯酰胺,阳离子聚丙烯酰胺,非离子聚丙烯酰胺厂家最新推荐,产能、专利、环保三维数据透视
  • 2025 年聚丙烯酰胺絮凝剂,PAM 聚丙烯酰胺,聚丙烯酰胺聚合氯化铝厂家最新推荐,产能、专利、环保三维数据透视
  • ST表
  • 吱吱企业即时通讯:赋能企业高效沟通与协作新生态
  • Windows Server 2022 OVF (2025 年 10 月更新) - VMware 虚拟机模板
  • Linux运行时常用命令
  • 2025年盘式干燥机厂家权威推荐榜单:回转滚筒干燥机/真空干燥机/沸腾干燥机源头厂家精选
  • Windows Server 2025 OVF (2025 年 10 月更新) - VMware 虚拟机模板
  • 同步盘哪个好用?坚果云、百度网盘等五大工具横向对比
  • 借助 ChatGPT API 将 AI 集成到测试自动化框架中
  • P11994 [JOIST 2025] 外郎糕 题解
  • 告别手动上传!10款自动同步本地文件夹的网盘深度评测
  • 腾讯CodeBuddy:AI IDE的革命性突破,开发者工作方式的彻底重塑
  • C++中STL容器应用
  • 2025 年德州清水混凝土修补,德州仿清水混凝土修补,德州外墙仿清水混凝土修补公司最新推荐,聚焦资质、案例、售后的五家企业深度解读
  • 2025 年德州混凝土修补,山东专业混凝土修补,山东建筑清水混凝土修补,山东装饰清水混凝土修补公司最新推荐,聚焦资质、案例、售后的五家企业深度解读
  • 前后端分离,千万别再搞错了!