Java:游戏的并发性
我正在编写 Bananagrams 的模拟以供娱乐。我想使用并发,但我不完全确定如何使用。
我在 Game 类中有一个 main 方法。每个玩家线程都致力于寻找解决方案。在某些时候,玩家会“剥离”。在此操作期间,每个玩家都会收到一张新牌。玩家线程之一必须通知 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
}
How can I Implement this in Java? (我不一定要寻找完全充实的解决方案,只是为我指明正确的方向。)我想如何处理对象之间的通知?
澄清一下:这不是一个用户交互游戏。我只是想尝试不同的算法,看看哪种算法可以最快地解决问题。如果有的话,“游戏”将编写一个算法并将其插入以查看它是如何工作的。
I'm writing a simulation of Bananagrams for fun. I want to use concurrency but I'm not entirely sure how.
I have a main method in a Game
class. Each of the player threads works towards a solution. At certain points, a player will "peel". During this operation, every player is dealt a new tile. One of the player threads must notify the Game
thread.
The pseudocode would look something like this:
while (no player has reported they are finished) {
if (player reports it is time to peel) {
everyone peel
}
everyone work towards completion of puzzle
}
How can I implement this in Java? (I'm not necessarily looking for fully fleshed out solutions, just point me in the right direction.) How do I want to handle notification between objects?
To clarify: this is not a user-interaction game. I just want to try different algorithms to see which can solve the problem the fastest. If anything, the "game" would be writing an algorithm and plugging it in to see how it works.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
这将是使用 的好地方循环势垒。
本质上,循环屏障让线程执行一些工作,然后让所有线程等待,直到它们都到达同一点,然后每个线程再次启动。
因此,您可以让每个玩家剥离,然后调用 CyclicBarrier.await()。然后所有线程将等待,直到每个线程都到达该点。这似乎就是你想要的。
(此外,您显然并不真正需要并发:)
This would be a good place to use a Cyclic Barrier.
Essentially a Cyclic Barrier lets threads do some work, then have all the threads wait until they all get to the same point, then each thread starts again.
So, you could have each player peel, then call CyclicBarrier.await(). All the threads will then wait until each has reached that point. Which seems to be what you want.
(Also, you obviously don't really need concurrency for this :)
根据您的流程的具体情况,您可能不需要进行线程(相信我,如果可能的话,您宁愿避免线程,无论大孩子们认为它有多酷和有趣)。
解决该问题的一种方法是设置事件队列。
伪代码
所以在这里,您可以每秒运行事件循环 25 次、30 次或 60 次,无论您想要以什么帧速率运行。你为此使用一个计时器(我确信java中某处有一个计时器)
然后doEvent将尝试在相应的播放器实例上查找一些相应的方法。 Squid 类上的工作方法将执行一些微小的工作,然后停止,等待循环中的下一次。阵列中的每个鱿鱼轮流做自己的一小部分工作。反过来,工作方法可以将 PEEL 事件放入事件队列中。此时,下一次循环时,可能会调用一些相应的剥离方法。也许在某个中央游戏类上,带有发起剥离事件的玩家的 ID。您将如何分派这些事件的逻辑放入 doEvent 方法中。 doEvent 又可以将一个对象传递给每个事件接收器,以便接收器可以将自己的事件对象放入队列中,以便下次循环运行。 或者,“针对每个事件”循环运行直到事件队列为空,其中包括之前调用 doEvent 刚刚添加的新事件,因此可以立即调用新事件,而不是等待下一帧动画)
( 正在弄清楚如何将长时间运行的工作分解为一小部分工作,弄清楚如何保存该工作的结果,并在下次调用工作方法时从上次中断的地方继续进行。如果所有玩家都表现良好,他们都可以共享一个线程而不会被卡住。
如果您要走线程路径,那么谁可以访问哪些内存以及何时访问的问题会变得更加复杂。
Depending on exactly what your process is, you might not need to do threading (Which, trust me, is something that you'd rather avoid if at all possible, no matter how cool and fun the big kids make it out to be).
One way to approach the problem is to set up an event queue.
in pseudocode
So here you run the event loop 25 times, 30 times, or 60 times per second, whatever frame rate you want to operate at. You use a timer for that (i'm sure there's one in java somewhere)
Then doEvent will try and look up some cooresponding method on the cooresponding player instance. The work method on the Squid class will do some tiny parcel of work, and then stop, waiting for the next time around in the loop. Each Squid in the array gets their turn to do their tiny bit of work. The work method, in turn, MAY put a PEEL event onto the event queue. At that point, next time around the loop, some cooresponding peel method may be called. Perhaps on some central game class, with the id of the player that originated the peel event. You put the logic of how to dispatch these events into the doEvent method there. doEvent in turn can pass in an object to each event reciever, so that the reciever can put their own event objects onto the queue to be run next time around the loop. (alternately, the "for each event" loop runs until the eventqueue is empty, and that includes new events just added by previous calls to doEvent, so a new event can get called immediately instead of waiting for the next frame of animation)
The trick is figuring out how to break your long running work into a tiny parcel of work, figure out how to save the results of that work, and pick it up later where you left off the next time the work method is called. If all the players are well behaved, they can all share a thread without getting stuck.
If you're going to go down the threaded path, the issues about who can access what bit of memory and when get a little bit more complicated.
观察者模式可能是合适的。每个人都在主线程中注册以接收有关剥离事件的通知。当一个人报告剥离时间到时,他会通知主线程,主线程又通知所有已注册的线程。通知可以通过一个特殊的线程局部变量(每个玩家线程都有自己的变量)来完成,该变量由主线程通过方法调用进行设置,并由玩家线程在游戏循环的每次迭代中进行检查。
编辑:这里有一篇文章的链接,该文章更深入地介绍了如何在 Java 中以多线程方式实现观察者模式。 http://www.javaworld.com/jw-03- 1999/jw-03-toolbox.html
The Observer pattern might be appropriate. Everyone registers with the main thread to receive notifications on peel events. When one person reports that its time to peel, he notifies the main thread, who in turn notifies all registered threads. Notification could be done through a special thread-local variable (each player thread has his own) that is set by the main thread via a method call and checked by the player thread at each iteration of the game loop.
Edit: here's a link to an article that goes more into depth regarding implementing the Observer pattern in multithreaded fashion in Java. http://www.javaworld.com/jw-03-1999/jw-03-toolbox.html