当前位置: 首页 > 知识库问答 >
问题:

Java中使用信号量的循环线程

任繁
2023-03-14

我想使用4个线程和信号量来实现fizzbizz游戏。
我设法使线程按照所需的顺序工作:fizz()->buzz()->fizzBuzz()->printNumber()
然而,我无法使整个过程循环。
每个方法都有自己的信号量,尽管在释放下一个方法信号量之前锁定了自己的信号量,但这些方法只是不挂起第二个获取(实际上是方法中的第一个)。

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个答案

邢卓
2023-03-14

如果你坚持这样做,我只是让代码使用五个信号量,因为四个信号量不能形成一个稳定的循环。

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();
    }
}

结果如下所示:

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
...
 类似资料:
  • 为什么我们要在while循环后面加一个分号()? 我以以下代码为例: 那么在这里做什么呢?

  • null 更新 在OS X上,sem_init()没有按预期工作。使用sem_open()来解决这个问题。参考:http://lists.apple.com/archives/darwin-dev//2008/oct/msg00044.html

  • 1“如何确保线程按特定顺序执行”这个问题的答案是正确地使用join()方法(参考:http://beginnersbook.com/2015/03/thread-join-method-in-java-with-example/). 2 15.5中的一个问题在下面的CiCt第6版中按顺序调用。 假设我们有以下代码: “同一个Foo实例将传递给三个不同的线程。线程A将首先调用,线程B将调用第二个,线

  • 本文向大家介绍python线程信号量semaphore使用解析,包括了python线程信号量semaphore使用解析的使用技巧和注意事项,需要的朋友参考一下 这篇文章主要介绍了python线程信号量semaphore使用解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 一.semaphore信号量原理 多线程同时运行,能提高程序的运行效率,但

  • 问题内容: 我正在使用从队列中连续读取的线程。 就像是: 停止此线程的最佳方法是什么? 我看到两个选择: 1-由于已弃用,因此我可以实现使用原子检查条件变量的方法。 2-将死亡事件对象或类似的对象发送到队列。当线程获取死亡事件时,它退出。 我更喜欢第一种方法,但是,我不知道何时调用该方法,因为可能有某种方法进入队列,并且停止信号可能首先到达(这是不希望的)。 有什么建议? 问题答案: 该(或因为它

  • 我想用java信号量解决用餐哲学家的问题,但我被卡住了。最高ID的筷子应该是可用的,但它似乎总是采取,我不知道为什么。谁能告诉我我错在哪里了? Fork类: 哲学家班: 主要内容: