leetcode
leetcode 1101 ~ 1150
交替打印字符串

交替打印字符串

难度:

标签:

题目描述

代码结果

运行时间: 26 ms, 内存: 16.6 MB


/*
思路: 使用Java Stream的方式, 对1到n的整数进行遍历, 判断每个数字是否能被3、5或3和5同时整除, 
并使用相应的输出方法来打印对应的字符串或数字。
*/
import java.util.stream.IntStream;

public class FizzBuzzStream {
    public static void fizzBuzz(int n) {
        IntStream.rangeClosed(1, n).forEach(i -> {
            if (i % 3 == 0 && i % 5 == 0) {
                System.out.println("fizzbuzz");
            } else if (i % 3 == 0) {
                System.out.println("fizz");
            } else if (i % 5 == 0) {
                System.out.println("buzz");
            } else {
                System.out.println(i);
            }
        });
    }
}

解释

方法:

这个题解使用了四个线程来并发处理从1到n的数字,每个线程根据数字的特性(能否被3、5整除)来执行特定的打印任务。利用锁(Lock)和条件变量(Condition)来同步不同的线程,确保在任意时刻只有一个线程能够执行并修改共享资源current的值。每个方法(fizz, buzz, fizzbuzz, number)对应一个线程,它们在内部循环中检查当前数字(self.current)是否符合打印条件,如果符合则打印并通知其他线程,否则等待其他线程的通知。

时间复杂度:

O(n)

空间复杂度:

O(1)

代码细节讲解

🦆
在FizzBuzz类中,如何确保在多个线程中同时只有一个线程能够修改`self.current`值?
在FizzBuzz类中,使用了一个锁(Lock)和条件变量(Condition)来确保同一时间只有一个线程可以修改`self.current`的值。每个线程在尝试读取或修改`self.current`之前必须先获取锁。这是通过`with self.lock:`语句块实现的,该语句块确保了在该块内的代码执行期间,当前线程持有锁。这样,当一个线程在修改`self.current`时,其他线程会被阻塞,直到锁被释放,确保了对`self.current`的访问和修改是线程安全的。
🦆
为什么每个条件检查后都要调用`self.cv.notify_all()`而不是`self.cv.notify()`?
调用`self.cv.notify_all()`而不是`self.cv.notify()`确保所有等待的线程都被通知并有机会获取锁来检查条件是否已经满足其需要。因为该问题设计四个线程分别负责不同的打印任务,如果使用`self.cv.notify()`,则只会随机唤醒一个等待中的线程,这可能导致必要的条件更新被延迟处理,比如当前数字适合多个打印条件但只唤醒了一个相关线程。使用`self.cv.notify_all()`可以减少这种情况的发生,确保程序的正确性和效率。
🦆
如果数字n非常大,这种多线程方法相比单线程有什么明显的性能提升吗?
如果数字n非常大,多线程方法相比单线程可能会有一定的性能提升,但这种提升可能不如预期明显。这是因为虽然多线程可以并行处理不同的打印任务(如fizz、buzz、fizzbuzz和number),但由于所有线程共享访问和修改同一个变量`self.current`,频繁的锁操作和线程间的同步可能导致较大的开销。此外,线程调度和上下文切换也可能增加额外的开销。因此,性能提升的程度依赖于系统的多线程管理效率和具体实现方式。
🦆
在多线程环境下,`self.cv.wait()`会如何影响程序的效率和线程的调度?
在多线程环境下,`self.cv.wait()`会使调用它的线程挂起,直到其他线程通过`self.cv.notify()`或`self.cv.notify_all()`发出通知。这个操作涉及线程的挂起和唤醒,会导致线程上下文切换,这是一个相对昂贵的操作。频繁的使用`self.cv.wait()`和对应的唤醒操作会增加系统的负担,降低程序的整体效率。此外,如果不当使用(如在不适当的时机调用`wait()`),可能导致死锁或者程序逻辑错误。因此,虽然`self.cv.wait()`是线程同步中必要的工具,但需要谨慎使用,确保在合适的逻辑和条件下调用。

相关问题