Я бы хотел реализовать игру FizzBizz
, используя 4 потока и семафоры.
Мне удалось заставить потоки работать в нужном порядке: fizz() -> buzz() -> fizzBuzz() -> printNumber()
.
Однако мне не удалосьсделайте всю процедуру круглой.
Каждый метод имеет свой собственный семафор, и, несмотря на блокировку своего собственного семафора перед выпуском семафора следующего метода, методы просто не зависают при втором получении (которое является первым в методе)., на самом деле).
Желаемое поведение:
1. Заблокировать все семафоры.
2. Запустить все 4 метода.
3. Отпустить fizz()
семафор, чтобы он пошел первым.
4.fizz()
завершает работу, снимает buzz()
блокировку и зависает до тех пор, пока printNumber()
не освободит ее.
5. и т. Д.
import java.util.concurrent.Semaphore;
import java.util.concurrent.atomic.AtomicLong;
class FizzBuzz {
protected AtomicLong num = new AtomicLong(1);
protected AtomicLong n = new AtomicLong(100);
protected Semaphore sem1 = new Semaphore(1);
protected Semaphore sem2 = new Semaphore(1);
protected Semaphore sem3 = new Semaphore(1);
protected Semaphore sem4 = new Semaphore(1);
public void start() {
System.out.println("Started");
try {
sem1.acquire();
sem2.acquire();
sem3.acquire();
sem4.acquire();
this.fizz();
this.buzz();
this.fizzBuzz();
this.printNumber();
sem1.release();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void fizz() {
new Thread() {
@Override
public void run() {
while (num.get() <= n.get()) {
try {
// System.out.println("Fizz waiting...");
sem1.acquire();
sem1.release();
if (num.get() > n.get()) {
break;
}
if (num.get() % 3 == 0 && num.get() % 5 != 0) {
num.getAndIncrement();
System.out.println("Fizz");
}
sem1.acquire();
sem2.release();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
}
public void buzz() {
new Thread() {
@Override
public void run() {
while (num.get() <= n.get()) {
try {
// System.out.println("Buzz waiting...");
sem2.acquire();
sem2.release();
if (num.get() > n.get()) {
break;
}
if (num.get() % 5 == 0 && num.get() % 3 != 0) {
num.getAndIncrement();
System.out.println("Buzz");
}
sem2.acquire();
sem3.release();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
}
public void fizzBuzz() {
new Thread() {
@Override
public void run() {
while (num.get() <= n.get()) {
try {
// System.out.println("FizzBuzz waiting...");
sem3.acquire();
sem3.release();
if (num.get() > n.get()) {
break;
}
if (num.get() % 3 == 0 && num.get() % 5 == 0) {
num.getAndIncrement();
System.out.println("FizzBuzz");
}
sem3.acquire();
sem4.release();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
}
public void printNumber() {
new Thread() {
@Override
public void run() {
while (num.get() <= n.get()) {
try {
// System.out.println("Print Number waiting...");
sem4.acquire();
sem4.release();
if (num.get() > n.get()) {
break;
}
if (num.get() % 3 == 1 && num.get() % 5 == 1) {
num.getAndIncrement();
System.out.println(num);
}
sem4.acquire();
sem1.release();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
}
}