【问题标题】:Multithreaded Round Robin Tournament多线程循环锦标赛
【发布时间】:2012-07-31 03:48:04
【问题描述】:

我正在尝试测试 8 种不同的游戏算法。这些算法可以与遵循游戏界面的不同类型的游戏相互对抗。

所以,他们必须互相对抗 100 场比赛。我已经完成了那部分,它工作正常。现在,我正在尝试使其成为多线程,以利用朋友计算机的 8 核。

我很少有使用线程的经验。那么,为了使我的代码成为多线程,我必须进行哪些更改?

这是我的单线程版本的代码。

编辑:我想到的解决方案(以我的基本知识)是关于制作一个 Match 类,它需要两个玩家和他们想要玩的游戏。该类将实现 Runnable,我可以为每个游戏创建一个线程。我现在的问题是,一旦 run() 方法完成,我将如何通知结果?

谢谢

for (int p1 = 0; p1 < allPlayers.length; p1++)
{
    for (int p2 = p1 + 1; p2 < allPlayers.length; p2++)
    {    
        for (int t = 0; t < trials; t++)
        {
            int player1 = t % 2 == 0 ? p1 : p2;
            int player2 = t % 2 == 0 ? p2 : p1;
            Player[] players = new Player[] { allPlayers[player1], allPlayers[player2] };
            game.newGame();

            while (!game.isFinished())
                game.playNthMove(players[game.currentPlayer()].move(game));

            data[p1][p2][t] = getCharValue(game.getOutcome()[t % 2 == 0 ? 0 : 1]);
            data[p2][p1][t] = getCharValue(game.getOutcome()[t % 2 == 0 ? 1 : 0]);
        }
    }
}

【问题讨论】:

    标签: java multithreading


    【解决方案1】:

    您不需要修改单线程实现的代码 - 您只需要创建一个实现 Runnable 接口的类并将该功能包装在 run() 方法中。然后你可以创建一个线程,传入该类的一个实例,然后调用Thread.start()

    参考this

    编辑:如何从该线程获取结果:

    看起来 Callable Interface 就是您要寻找的。这是link,其中包含有关如何使用它的基本说明。它需要了解如何使用 Runnable 接口来创建没有结果的多线程应用程序的基本知识,所以我建议先阅读this

    【讨论】:

    • 那么,我是否需要像 Match 类这样的东西,在其中传递两个玩家和他们想要玩的游戏,并且该类应该实现可运行的接口让我们说?那么,游戏结束后会发生什么?如何通知结果?
    • @wanstein 老实说,我从来没有在 Java 中使用过多线程应用程序——尽管我在 C# 中使用它们有相当多的经验。从这个角度来看,是的,我会先创建一个实现 Runnable 的类,它可以通过两个玩家和他们想要玩的游戏,并且可以运行游戏。
    • @wanstein 至于如何获得结果,在 C# 中,我的第一反应是在主线程上触发一个事件,并将结果作为 EventArg 传递。不过,我不认为 Java 是这样工作的。经过一番谷歌搜索,我找到了这个link,它解释了如何使用 Callable 从另一个线程返回值,并包含一个简单的示例。
    【解决方案2】:
    Collection<Callable<Void>> tasks = new ArrayList<Callable<Void>();
    for (int p1 = 0; p1 < allPlayers.length; p1++)
    {
        for (int p2 = p1 + 1; p2 < allPlayers.length; p2++)
        {    
            for (int t = 0; t < trials; t++)
            {
                final int player1 = t % 2 == 0 ? p1 : p2;
                final int player2 = t % 2 == 0 ? p2 : p1;
                final Player[] players = new Player[] { allPlayers[player1], allPlayers[player2] };
                final int trial = t;
                tasks.add(new Callable<Void>() {
                   public Void call() {
                     game.newGame();
    
                     while (!game.isFinished())
                        game.playNthMove(players[game.currentPlayer()].move(game));
    
                     data[p1][p2][t] = getCharValue(game.getOutcome()[t % 2 == 0 ? 0 : 1]);
                     data[p2][p1][t] = getCharValue(game.getOutcome()[t % 2 == 0 ? 1 : 0]);
                     return null;
                  }
               });
            }
        }
    }
    executor.invokeAll(tasks); // called on an exector, will wait for all tasks to complete
    

    当前设计的问题是游戏对象看起来不是线程安全的。您可能希望每个 Runnable 都有一个新的游戏对象。

    【讨论】:

      【解决方案3】:

      没有灵丹妙药。在问这个问题之前,您需要了解基础知识。从阅读 MSDN 上的这篇文章开始:http://msdn.microsoft.com/en-us/magazine/cc163744.aspx。 Java 也差不多。

      完成后,回来就你自己尝试遇到的问题提出另一个问题。

      当然,您可能会在这里得到另一个答案,告诉您该怎么做。但是,不要阅读那个答案。在继续之前了解基础知识至关重要。否则,当您的应用停止运行时,您将完全迷失。

      【讨论】:

      • 我对否决票没有任何问题。但是解释一下原因,以便我可以向他们学习。
      • 好吧,我根本没想到会有一个完整的解决方案。我期待有人告诉我这样的事情:每次匹配使用线程,使用执行器,使用线程池等。我期待更多的是可能的解决方案的想法,从哪里开始,而不是编码的解决方案。跨度>
      • 我编辑了这个问题,让我知道我打算做什么。更好?
      • 我已经警告过你了。听不听就看你自己了。至于通知,只需添加一个在Match 线程完成时调用的简单事件。您可以使用thread.Join 等待正在运行的线程/匹配。
      猜你喜欢
      • 2017-09-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-05-21
      • 1970-01-01
      • 2019-10-07
      • 2012-04-03
      • 2019-08-02
      相关资源
      最近更新 更多