Круговые потоки в Java с использованием семафоров - PullRequest
0 голосов
/ 08 июля 2019

Я бы хотел реализовать игру 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();
    }
}

1 Ответ

0 голосов
/ 09 июля 2019

Если вы настаиваете на этом, я просто делаю код, который использует пять семафоров, потому что четыре семафора не могут образовывать стабильный круг.

package exercise.concurrency;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;

public class SemaphoreTest {
    public static void main(String[] args) {
        new FizzBuzz().start();
    }

}




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);
    protected Semaphore sem5 = new Semaphore(1);

    public void start() {
        System.out.println("Started");
        try {
            sem1.acquire();
            sem2.acquire();
            sem3.acquire();
            sem4.acquire();
            sem5.acquire();
            this.fizz();
            this.buzz();
            this.fizzBuzz();
            this.printNumber();


        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void fizz() {
        new Thread() {
            @Override
            public void run() {
                 sem1.release();
                 sem5.release();
                while (num.get() <= n.get()) {
                    try {
                        sem1.acquire();
                        sem5.acquire();
                        if (num.get() > n.get()) {
                            break;
                        }
                        if (num.get() % 3 == 0 && num.get() % 5 != 0) {
                            num.getAndIncrement();
                            System.out.println("Fizz");
                        }
                        System.out.println("1.fizz one loop");
                        TimeUnit.MILLISECONDS.sleep(500);
                        sem2.release();
                        sem5.release();
                        Thread.yield();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
                System.out.println("fizz has finshed");
            }
        }.start();
    }

    public void buzz() {
        new Thread() {
            @Override
            public void run() {
                while (num.get() <= n.get()) {
                    try {
                        sem2.acquire();
                        sem5.acquire();
                        if (num.get() > n.get()) {
                            break;
                        }
                        if (num.get() % 5 == 0 && num.get() % 3 != 0) {
                            num.getAndIncrement();
                            System.out.println("Buzz");
                        }
                       System.out.println("2.buzz one loop");
                       TimeUnit.MILLISECONDS.sleep(500);
                       sem3.release();
                       sem5.release();
                       Thread.yield();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        }.start();
    }

    public void fizzBuzz() {
        new Thread() {
            @Override
            public void run() {
                while (num.get() <= n.get()) {
                    try {
                        sem3.acquire();
                        sem5.acquire();
                        if (num.get() > n.get()) {
                            break;
                        }
                        if (num.get() % 3 == 0 && num.get() % 5 == 0) {
                            num.getAndIncrement();
                            System.out.println("FizzBuzz");
                        }
                        System.out.println("3.fizzBuzz one loop");
                        TimeUnit.MILLISECONDS.sleep(500);
                        sem4.release();
                        sem5.release();
                        Thread.yield();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        }.start();
    }

    public void printNumber() {
        new Thread() {
            @Override
            public void run() {
                while (num.get() <= n.get()) {
                    try {
                        sem4.acquire();
                        sem5.acquire();
                        if (num.get() > n.get()) {
                            break;
                        }
                        if (num.get() % 3 == 1 && num.get() % 5 == 1) {
                            num.getAndIncrement();
                            System.out.println(num);
                        }
                        System.out.println("4.printNumber one loop\n");
                        TimeUnit.MILLISECONDS.sleep(500);
                        sem1.release();
                        sem5.release();
                        Thread.yield();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        }.start();
    }
}

Он использует Thread.yield(), чтобы указать для механизма потоков, когда один поток делает один раз, когда другой может иметь шанс выполнить свою работу. TimeUnit.Millseconds.sleep() делает результат четким.

Результат выглядит так:

Started
1.fizz one loop
2.buzz one loop
3.fizzBuzz one loop
2
4.printNumber one loop

1.fizz one loop
2.buzz one loop
3.fizzBuzz one loop
4.printNumber one loop

1.fizz one loop
2.buzz one loop
3.fizzBuzz one loop
4.printNumber one loop

1.fizz one loop
2.buzz one loop
3.fizzBuzz one loop
4.printNumber one loop

1.fizz one loop
2.buzz one loop
3.fizzBuzz one loop
4.printNumber one loop

1.fizz one loop
...
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...