непонятна логика в задаче о многопоточном fizzbuzz
class FizzBuzz {
int n;
private final Semaphore semFizz;
private final Semaphore semBuzz;
private final Semaphore semFizzBuzz;
private final Semaphore semNumber;
public FizzBuzz(int n) {
this.n = n;
semFizz = new Semaphore(0);
semBuzz = new Semaphore(0);
semFizzBuzz = new Semaphore(0);
semNumber = new Semaphore(1);
}
public void fizz(Runnable printFizz) throws InterruptedException {
for (int i = 3; i <= n ; i+= 3) {
semFizz.acquire();
printFizz.run();
semNumber.release();
if ((i + 3) % 5 == 0) {
i += 3;
}
}
}
public void buzz(Runnable printBuzz) throws InterruptedException {
for (int i = 5; i <= n ; i += 5) {
semBuzz.acquire();
printBuzz.run();
semNumber.release();
if ((i + 5) % 3 == 0) {
i += 5;
}
}
}
public void fizzbuzz(Runnable printFizzBuzz) throws InterruptedException {
for (int i = 15; i <= n; i += 15) {
semFizzBuzz.acquire();
printFizzBuzz.run();
semNumber.release();
}
}
public void number(IntConsumer number) throws InterruptedException {
for (int i = 1; i <= n; i++) {
semNumber.acquire();
if((i % 3 == 0)&& (i % 5 == 0)){
semFizzBuzz.release();
}
else if(i % 5 == 0){
semBuzz.release();
}
else if(i % 3 == 0){
semFizz.release();
}
else{
number.accept(i);
semNumber.release();
}
}
}
}
class Number{
public static void main(String[] args) {
FizzBuzz fizzBuzz = new FizzBuzz(15);
Runnable printFizz = () -> System.out.print("fizz ");
Runnable printBuzz = () -> System.out.print("buzz ");
Runnable printFizzBuzz = () -> System.out.print("fizzbuzz ");
IntConsumer printNumber = number -> System.out.print(number + " ");
Thread threadA = new Thread(() -> {
try {
fizzBuzz.fizz(printFizz);
} catch (InterruptedException e) {
e.printStackTrace();
}
// System.out.println("А ЗАВЕРШЕН ");
});
Thread threadB = new Thread(() -> {
try {
fizzBuzz.buzz(printBuzz);
} catch (InterruptedException e) {
e.printStackTrace();
}
// System.out.println("В ЗАВЕРШЕН ");
});
Thread threadC = new Thread(()-> {
try {
fizzBuzz.fizzbuzz(printFizzBuzz);
} catch (InterruptedException e) {
e.printStackTrace();
}
// System.out.println("С ЗАВЕРШЕН ");
});
Thread threadD = new Thread(() -> {
try {
fizzBuzz.number(printNumber);
} catch (InterruptedException e) {
e.printStackTrace();
}
// System.out.println("D ЗАВЕРШЕН ");
});
threadA.start();
threadB.start();
threadC.start();
threadD.start();
}
}
Задача: Нужно напечатать числа от 1-n.
Каждое кратное 3-м заменить на "fizz"
Каждое кратное 5-ти заменить на "buzz"
Каждое кратное 15-ти заменить на "fizzbuzz"
Для этого в классе есть 4 метода и нужно задачу решить так, чтобы создавались 4 потока, в них мы передавали эти методы и задача отрабатывала.
Решение вверху верное.
Я понимаю все, кроме строк в методе "fizz"
if ((i + 3) % 5 == 0) {
i += 3;
}
и в методе "buzz"
if ((i + 5) % 3 == 0) {
i += 5;
}
Оьъясните, пожалуйста, почему потоки не завершаются без этих действий
Ответы (1 шт):
Эти действия позволяют физу и базу перепрыгнуть через число, делящееся на 15, потому что его должен печатать физбаз.
Почему виснет - не хочу разбираться.
Подозреваю, что если не перепрыгивать, то эта система костыльков и верёвочек из четырёх семафоров, каждый из которых ставится в одном методе, а снимается в другом (ну антипаттерн в четвёртой степени, же), идёт в разнос и виснет.