Java:游戏的并发性

时间:2009-12-26 06:38:27

标签: java concurrency notify

我正在写一个Bananagrams模拟的乐趣。我想使用并发,但我不完全确定如何。

我在Game课程中有一个主要方法。每个玩家线程都致力于解决方案。在某些时候,玩家将“剥离”。在此操作期间,每个玩家都会获得一个新牌。其中一个玩家线程必须通知Game线程。

伪代码看起来像这样:

while (no player has reported they are finished) {
      if (player reports it is time to peel) {
           everyone peel 
      }
      everyone work towards completion of puzzle
}

如何在Java中实现它? (我不一定在寻找完全充实的解决方案,只需指出正确的方向。)我如何处理对象之间的通知?

澄清:这不是用户互动游戏。我只是想尝试不同的算法,看看哪个可以最快地解决问题。如果有的话,“游戏”将编写一个算法并将其插入以查看它是如何工作的。

3 个答案:

答案 0 :(得分:4)

这是使用Cyclic Barrier的好地方。

本质上,循环障碍允许线程做一些工作,然后让所有线程等到它们都到达同一点,然后每个线程再次启动。

所以,你可以让每个玩家都去掉,然后调用CyclicBarrier.await()。然后所有线程将等待,直到每个线程都到达该点。这似乎是你想要的。

(另外,你显然不需要并发这个:)

答案 1 :(得分:1)

观察者模式可能是合适的。每个人都注册主线程以接收剥离事件的通知。当一个人报告剥离时间时,他会通知主线程,主线程又会通知所有已注册的线程。通知可以通过一个特殊的线程局部变量(每个玩家线程都有自己的)来完成,该变量由主线程通过方法调用设置,并在游戏循环的每次迭代中由玩家线程检查。

编辑:这是一篇文章的链接,该文章更深入地介绍了如何在Java中以多线程方式实现Observer模式。 http://www.javaworld.com/jw-03-1999/jw-03-toolbox.html

答案 2 :(得分:1)

根据你的过程究竟是什么,你可能不需要做线程(相信我,如果可能的话,你宁愿避免使用线程,无论大孩子们多么酷和有趣定)。

解决问题的一种方法是设置事件队列。

在伪代码中

 enum EVENTTYPES = {PEEL=0, WORK=1};
 struct Event = {
     int eventType;
     int* data;
 }

 filoQueue eventQueue;

 array sQuidPlayers = [new Squid(), new Squid(), new Squid()];
 void eventLoop () {
      int player;
      for each player in sQuidPlayers {
          eventQueue.push(new Event(EVENTTYPES.WORK, player.id));
      }

      for each event in eventQueue {
           game.doEvent(event)
      }

 }

所以在这里你运行事件循环每秒25次,30次或60次,无论你想要操作什么帧速率。你使用一个计时器(我确定在某个地方有一个)

然后doEvent将尝试在cooresponding播放器实例上查找一些cooresponding方法。 Squid类的工作方法将做一些微小的工作,然后停止,等待下一次循环。阵列中的每个Squid轮到他们完成他们的一小部分工作。反过来,工作方法可以将PEEL事件放到事件队列中。此时,下一次循环,可以调用一些相应的剥离方法。也许在一些中央游戏类中,玩家的id发起了剥离事件。您将如何将这些事件分配到doEvent方法的逻辑。反过来,doEvent可以将一个对象传递给每个事件接收器,这样接收者就可以将自己的事件对象放到队列中,以便下次循环运行。 (或者,“for each event”循环运行直到eventqueue为空,并且包括刚刚通过之前调用doEvent添加的新事件,因此可以立即调用新事件而不是等待下一帧动画)

诀窍是弄清楚如何将长期工作分解成一小块工作,找出如何保存工作的结果,并在下次调用工作方法时离开的地方捡起工作。如果所有玩家表现良好,他们都可以共享一个线程而不会卡住。

如果您要沿着线程路径前进,那么关于谁可以访问哪些内存以及何时变得更复杂的问题。