Android:线程没有并行运行

awr*_*awr 6 multithreading android opengl-es-2.0

我正在用Android/OpenGL编写一个游戏,并试图将我的OpenGL(渲染)逻辑与我的游戏更新逻辑分开,方法是在自己的线程上运行每个逻辑以提高性能.

我设法让每个都在自己的线程上运行,但是根据DDMS中的Tracer,线程仍在顺序运行(世界是我的游戏更新线程):

请参阅url,因为我没有图像权限:http: //img849.imageshack.us/img849/9688/capturegff.png

线程似乎不会同时执行代码.我初始化世界线程如下:

public class World implements Runnable {

    Thread thread;

    public World(...) {
    ...
        // Initialise the player/ball objects
        initialiseObjects();

        thread = new Thread(this, "World");
        thread.start();
}
}
Run Code Online (Sandbox Code Playgroud)

我在两个线程之间实现了自己的同步.使用类似于Replica Island的方法,我有两个渲染缓冲区:当渲染线程正在读取另一个缓冲区时,更新线程(理想情况下应该)写入其中一个缓冲区.缓冲区包含渲染器绘制每个精灵所需的信息.一旦更新线程完成更新其缓冲区并且渲染器已完成绘制,它们将交换缓冲区并重复该过程.

在游戏更新线程的代码中(渲染线程中的类似代码):

    currBuffer.write();
    player.draw(currBuffer.getNext());

   ball.draw(currBuffer.getNext());

    if (particleEffect != null) {
        particleEffect.draw(currBuffer);
    }

    currBuffer.finished();

    while(otherBuffer.isFinished() == false) {
        //otherBuffer is finished once the render thread has finished drawing
    }

    DrawBuffer tempBuffer = currBuffer;
    currBuffer = otherBuffer;
    otherBuffer = tempBuffer;

    currBuffer.changed();
    while(otherBuffer.isChanged() == false) {
        //otherBuffer is changed once the render thread has also swapped buffered
    }
Run Code Online (Sandbox Code Playgroud)

我无法看到上面的代码如何导致线程的顺序执行,尽管我之前从未尝试过多线程,所以我可能会做一些根本错误的事情.我试图加速游戏的速度明显变慢,而且不那么顺畅.知道线程没有并行运行的原因吗?

更新:问题是我的手机的处理器只是单核心.我确信Incredible S是双核心,但它只是单一的.我在S2上尝试过,它确实并行运行了线程.

然而,如果只有市场上较新的手机支持多线程,那么多线程的优势是什么呢?我不明白Replica Island如何通过实现多线程在旧的单核手机上实现更好的性能.当然,如果没有第二个核心可以利用,那么线程之间同步的额外开销会导致性能降低?

由于必须生成缓冲区然后传递给绘制线程,多线程导致单核上的性能降低.在双核上,它快5-10%,但在大约500个精灵处,由于缓冲,更新周期再次比绘制周期长,从而限制了速度增益.显然,通过优化,我可以改进这一点,但问题在于是否值得以单核处理器为代价支持多线程.是否可以确定手机的处理器以确定是否在运行时使用多线程?

yig*_*git 2

嗯,从技术上讲,1 个 CPU 一次仅运行一个代码段。您的操作系统调度程序会在几毫秒内更改进程/线程,这会给您同时运行多个进程的错觉。

通知运行时线程现在已完成的一种方法是调用Thread.yield。您的代码中有一个繁忙的循环,这对您的情况没有帮助。它使 CPU 保持忙碌而不做任何事情。

while(otherBuffer.isFinished() == false)
Run Code Online (Sandbox Code Playgroud)

您应该使用Loks而不是 busy 循环,或者您可以尝试Thread.yield在 while 循环内调用以提高初始性能。顺便说一句,还要看看信号量,这是解决此类生产者-消费者问题的最简单的解决方案。如果您想保留当前的代码库,可以对每个缓冲区使用一个锁。