LeetCode刷题之旅【多线程篇-2】中等: 1195. 交替打印字符串
程序员文章站
2022-05-05 15:15:56
...
2019年11月18日
原题:https://leetcode-cn.com/problems/fizz-buzz-multithreaded/
目录 交替打印字符串
题目 交替打印字符串
解题1
加锁确保操作原子性,AtomicInteger 确保原子性
class FizzBuzz {
private int n;
private Object lock = new Object();
AtomicInteger count = new AtomicInteger(1);
public FizzBuzz(int n) {
this.n = n;
}
// printFizz.run() outputs "fizz".
// 线程A将调用 fizz() 来判断是否能被 3 整除,如果可以,则输出 fizz。
public void fizz(Runnable printFizz) throws InterruptedException {
while (count.get() <= n){
synchronized (lock){
if (count.get() <= n && count.get() % 3 == 0 && count.get() % 5 != 0){
printFizz.run();
count.incrementAndGet();
}
}
}
}
// printBuzz.run() outputs "buzz".
// 线程B将调用 buzz() 来判断是否能被 5 整除,如果可以,则输出 buzz。
public void buzz(Runnable printBuzz) throws InterruptedException {
while (count.get() <= n){
synchronized (lock){
if (count.get() <= n && count.get() % 5 == 0 && count.get() % 3 != 0){
printBuzz.run();
count.incrementAndGet();
}
}
}
}
// printFizzBuzz.run() outputs "fizzbuzz".
// 线程C将调用 fizzbuzz() 来判断是否同时能被 3 和 5 整除,如果可以,则输出 fizzbuzz。
public void fizzbuzz(Runnable printFizzBuzz) throws InterruptedException {
while (count.get() <= n){
synchronized (lock){
if (count.get() <= n && (count.get() % 5 == 0 && count.get() % 3 == 0)){
printFizzBuzz.run();
count.incrementAndGet();
}
}
}
}
// printNumber.accept(x) outputs "x", where x is an integer.
// 线程D将调用 number() 来实现输出既不能被 3 整除也不能被 5 整除的数字。
public void number(IntConsumer printNumber) throws InterruptedException {
while (count.get() <= n){
synchronized (lock){
if (count.get() <= n && (count.get() % 5 != 0 && count.get() % 3 != 0)){
printNumber.accept(count.get());
count.incrementAndGet();
}
}
}
}
}
解题2
一个网友角度新颖的解题方法:体现了Java并发包工具的方便。设立static(静态唯一)的CyclicBarrier(等待其他线程都一起触发之后,才进行下一步操作。)。
class FizzBuzz {
private int n;
private static CyclicBarrier barrier = new CyclicBarrier(4);
public FizzBuzz(int n) {
this.n = n;
}
// printFizz.run() outputs "fizz".
public void fizz(Runnable printFizz) throws InterruptedException {
for (int i = 1; i <= n; i++) {
if (i % 3 == 0 && i % 5 != 0) {
printFizz.run();
}
try {
barrier.await();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}
}
// printBuzz.run() outputs "buzz".
public void buzz(Runnable printBuzz) throws InterruptedException {
for (int i = 1; i <= n; i++) {
if (i % 3 != 0 && i % 5 == 0) {
printBuzz.run();
}
try {
barrier.await();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}
}
// printFizzBuzz.run() outputs "fizzbuzz".
public void fizzbuzz(Runnable printFizzBuzz) throws InterruptedException {
for (int i = 1; i <= n; i++) {
if (i % 3 == 0 && i % 5 == 0) {
printFizzBuzz.run();
}
try {
barrier.await();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}
}
// printNumber.accept(x) outputs "x", where x is an integer.
public void number(IntConsumer printNumber) throws InterruptedException {
for (int i = 1; i <= n; i++) {
if (i % 3 != 0 && i % 5 != 0) {
printNumber.accept(i);
}
try {
barrier.await();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}
}
}
解题3
方法一:锁
分析:
设置一个每个线程共有的变量i,用来代表当前的数字
将每一个判断并打印的操作,放在一个同步代码块内部,以保证操作的原子性,使得所有操作串行发生
每一个线程内部,当i小于等于n时,不断的争用同一把锁。
当线程得到锁后,判断当前的数字i是否满足自身的打印条件,若是则打印,并将i+1,否则放弃这把锁。
class FizzBuzz {
private int n;
private int i;
private Object lock = new Object();
public FizzBuzz(int n) {
this.n = n;
this.i = 1;
}
// printFizz.run() outputs "fizz".
public void fizz(Runnable printFizz) throws InterruptedException {
while (i <= n) {
synchronized(lock) {
while (i <= n && i % 3 == 0 && i % 5 != 0) {
printFizz.run();
i++;
}
}
}
}
// printBuzz.run() outputs "buzz".
public void buzz(Runnable printBuzz) throws InterruptedException {
while (i <= n) {
synchronized(lock) {
while (i <= n && i % 3 != 0 && i % 5 == 0) {
printBuzz.run();
i++;
}
}
}
}
// printFizzBuzz.run() outputs "fizzbuzz".
public void fizzbuzz(Runnable printFizzBuzz) throws InterruptedException {
while (i <= n) {
synchronized(lock) {
while (i <= n && i % 3 == 0 && i % 5 == 0) {
printFizzBuzz.run();
i++;
}
}
}
}
// printNumber.accept(x) outputs "x", where x is an integer.
public void number(IntConsumer printNumber) throws InterruptedException {
while (i <= n) {
synchronized(lock) {
while (i <= n && i % 3 != 0 && i % 5 != 0) {
printNumber.accept(i);
i++;
}
}
}
}
}
上一篇: eclipse整合hdfs环境 & 项目简单搭建示例
下一篇: Scrapy 常用pipeline