【问题标题】:How to use multithreads in java so that they take turns in a game如何在java中使用多线程以便它们在游戏中轮流
【发布时间】:2020-11-17 14:10:02
【问题描述】:

尝试使用 n 个线程,其中需要在两种不同类型的线程之间进行交换。 t1, x1, t2, x2, t3, x3.... 其中 x 和 t 是线程类。我一直在尝试使用等待和通知,但似乎无法让它工作。或同步。

所有线程都需要在各自的“轮次”中访问和修改相同的列表数组,我认为这可能是它自己的同步类,但也许原子变量也可以工作?

非常感谢任何帮助。

"""

public String startGame(int threadNumbers, List<String> result, String fileLoc) throws IOException {
        Players[] playerThreads = new Players[threadNumbers];
        Card[] cardThreads = new Card[threadNumbers];
        cardDeck cardD = new cardDeck(fileLoc);

        for (int i = 0; i < (threadNumbers); i++) {
                System.out.println(i);
                playerThreads[i] = new Players(i+1, cardD);
                if (i>0) {
                    playerThreads[i-1].next = cardThreads[i-0];
                }
                if (i==threadNumbers-1) {
                    playerThreads[i].next = cardThreads[0];
                }
                cardThreads[i] = new Card(i+1);
                if (i>0) {
                    cardThreads[i-1].next = playerThreads[i-0];
                }
                if (i==threadNumbers-1) {
                    cardThreads[i].next = playerThreads[0];
                }



            new Thread(playerThreads[i]).start();
            new Thread(cardThreads[i]).start();
            Thread.yield();
            Thread.yield();
        }
        synchronized (playerThreads[0]) {
            playerThreads[0].notify();

"""

这是行不通的,但需要做的是他们以循环的方式从牌库中取出一张牌,然后在他们有一手牌后开始游戏。卡线也只是手,但不同,因为它们不“玩”而只是工作。

【问题讨论】:

  • 是的,有n个线程,一次只能玩一个回合,会有很多等待
  • 理论上每个线程中运行的指令/代码是什么?
  • @jh6,对。那么使用不同的线程有什么意义呢?如果您想对一系列发生的事情进行建模,为什么不让一个线程按顺序执行每件事情呢?
  • 在多人模拟中使用线程的一个原因是模拟玩家在时的思考没有轮到他们。

标签: java multithreading synchronization thread-safety


【解决方案1】:

由于这似乎是多合一 (JVM) 进程,因此这里不需要多线程:只需使用队列来跟踪轮到谁以及接下来轮到谁。轮到一名玩家后,将他们重新添加到队列末尾。

实际上,现在我想起来了,同样的解决方案没有理由不能用于多个进程或通过套接字。

只需使用队列

-- 编辑--

所以你需要的是一个带有阻塞方法的类。例如

public class Player implements Runnable {
  private Move nextMove;

  public Move synchronized getMove() {
    if (!nextMove) {
      this.wait([add timeout if appropriate]);
    }
    Move next = nextMove;
    nextMove = null;
    return next;
  }

  public void run() {
    while (true) {
      Thread.sleep([someRandomTime]);
      synchronized(this) {
        if (nextMove == null) {
          nextMove = new Move();
          this.notify();
        }
      }
    }
  }
}

所以仍然使用你的队列,你遍历每个玩家并调用 getMove(),它会阻塞直到玩家发布移动。

顺便说一句,这种阻塞类似于 InputStream.read(buffer) 在套接字中的工作方式。调用 read 的线程一直等待,直到流的另一端发送一些内容。

-- 编辑2--

提醒一下:不要在 Thread 对象上使用同步、等待、通知或 notifyAll。

【讨论】:

  • 队列肯定是我解决这个问题的方式,如果它没有被指定为多线程的话。这真的让扳手在工作中发挥作用
猜你喜欢
  • 2023-03-12
  • 2014-12-28
  • 1970-01-01
  • 1970-01-01
  • 2013-12-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多