提问人:Ziggy 提问时间:11/8/2008 最后编辑:Ziggy 更新时间:8/25/2009 访问量:2438
如何使循环并排运行?
How do I make for loops run side by side?
问:
我一直在做一个幼稚的小程序:屏幕上有一堆不同颜色和大小的小圆圈。当一个较大的圆遇到一个较小的圆圈时,它会吃掉较小的圆圈,当一个圆圈吃掉足够多的其他圆圈时,它会繁殖。有点整洁!
然而,我实现它的方式,检测附近的圆圈并检查它们的可食用性的过程是通过一个 for 循环完成的,该循环遍历整个活的圆圈种群......这需要越来越长的时间,因为人口往往会在开始下降之前飙升到 3000 人。这个过程不会减慢我的电脑速度,我可以去玩《战争黎明》或其他游戏,而且没有任何减速:这只是检查每个圆圈的过程,看看它是否与其他每个圆圈相撞......
因此,我想到的是,我可以尝试将应用程序窗口分成四个象限,并让象限中的圆圈同时进行检查,因为它们几乎没有机会相互干扰:或者类似的东西!
那么,我的问题是:如何制作并排运行的循环?比如说,在 Java 中。
答:
如果您的计算机具有多个处理器或多个内核,那么您可以轻松地运行多个线程,并在每个线程中运行循环的较小部分。如今,许多 PC 确实有多个内核 - 因此,每个线程都获得 1/n 的循环计数,然后创建 n 个线程。
计算机通常是单任务的,这意味着它们通常可以一次执行每个 CPU 或内核的一条指令。
但是,正如您所注意到的,您的操作系统(和其他程序)似乎同时运行许多任务。
这是通过将工作拆分为多个进程来实现的,每个进程都可以通过生成线程来进一步实现并发性。然后,操作系统在每个进程和线程之间快速切换,给人一种多任务处理的错觉。
在您的情况下,您的 java 程序是一个进程,您需要创建 4 个线程,每个线程运行自己的循环。这可能会变得棘手,因为线程需要同步它们对局部变量的访问,以防止一个线程在另一个线程尝试访问变量时编辑变量。
因为线程是一个复杂的主题,所以需要比我在这里做的更多的解释。
但是,您可以阅读 Suns 关于并发的优秀教程,其中涵盖了您需要了解的所有内容:
http://java.sun.com/docs/books/tutorial/essential/concurrency/
评论
如果你真的想进入并发编程,你需要学习如何使用线程。
Sun 在这里有一个对 Java 线程进行编程的教程:http://java.sun.com/docs/books/tutorial/essential/concurrency/
你要找的不是让它们同时运行的方法(正如人们所指出的,这取决于你有多少个内核,并且只能提供 2 倍或 4 倍的加速),而是以某种方式减少你必须检测的碰撞数量。
您应该考虑使用四叉树。简而言之,您可以递归地将 2D 区域分解为四个象限(根据需要),然后只需要检测附近组件中对象之间的碰撞。在良好的情况下,它可以有效地将您的碰撞检测时间从 N^2 减少到 N * log N。
你在这里遇到的问题实际上可以在没有线程的情况下解决。
您需要的是一个空间数据结构。四边形树是最好的,或者如果球体移动的场是固定的(我假设是固定的),您可以使用简单的网格。这是这个想法。
将显示区域划分为一个正方形网格,其中每个单元格至少与最大圆一样大。对于每个单元格,保留一个列表(最好是链表),其中包含中心位于该单元格中的所有圆圈。然后,在碰撞检测步骤中,遍历每个单元格,并将该单元格中的每个圆圈与该单元格中的所有其他圆圈和周围单元格进行检查。
从技术上讲,您不必检查每个单元格周围的所有单元格,因为其中一些单元格可能已经被检查过。
您可以将此技术与多线程技术相结合,以获得更好的性能。
与其尝试进行并行处理,不如寻找碰撞检测优化。因为在许多情况下,在一个线程中执行较少的计算比在多个线程之间分配计算要好,而且在这种多线程业务中很容易陷入困境。尝试在谷歌上搜索“碰撞检测算法”,看看它能让你;)
评论
这听起来与我的一个实验非常相似 - 看看它......
我也对四叉树感兴趣(这就是我来这里的原因)......希望你都想通了。
评论