如何重新启动应用程序的更新循环

Posted

技术标签:

【中文标题】如何重新启动应用程序的更新循环【英文标题】:How to restart an update loop of an application 【发布时间】:2014-02-28 05:56:51 【问题描述】:

我正在使用 Java 和 Swing 开发绘图应用程序。只要布尔变量设置为true,它就有一个不断运行的不断更新循环。循环位于线程内。

它工作正常,但现在我希望循环仅在特定时间运行(仅在按下鼠标时),否则不运行。 (因此不会白白浪费内存)。

要停止循环,我只需将该变量设置为false。但我的问题是,停止循环后如何重新启动循环?将该变量设置回true 不会重新启动循环。有什么好的方法可以做到这一点?

编辑:我的(稍微简化的)循环:

public void run()

    int TICKS_PER_SECOND = 50;
    int SKIP_TICKS = 1000 / TICKS_PER_SECOND;
    int MAX_FRAMESKIP = 10;

    long next_game_tick = System.currentTimeMillis();
    int loops;

    boolean app_is_running = true;

    while( app_is_running ) 

        loops = 0;
        while( System.currentTimeMillis() > next_game_tick && loops < MAX_FRAMESKIP) 

            update();

            next_game_tick += SKIP_TICKS;
            loops++;
        

        repaint();
    


【问题讨论】:

@peeskillet 当然,看我的编辑 @peeskillet 是的,但据我所知,有时停止线程是一个问题,它相对困难(启动它当然很容易)。但从理论上讲,您是在建议我在暂停循环时停止线程并在想要重新启动循环时启动它? 请查看docs.oracle.com/javase/7/docs/api/java/awt/SecondaryLoop.html How to stop and restart a loop inside a thread?的可能重复 【参考方案1】:

使用Object.wait 在线程不运行时挂起它。让另一个线程调用 Object.notify 将其从睡眠中唤醒。

【讨论】:

【参考方案2】:

要每FRAME_RATE ms 执行一次线程主体,同时由外部定义的布尔值控制,run 方法可以这样构造:

public void run()

    long delay;
    long frameStart = System.currentTimeMillis();

    // INSERT YOUR INITIALIZATION CODE HERE

    try
    
        while (true)
        
            if (active)  // Boolean defined outside of thread
            
                // INSERT YOUR LOOP CODE HERE
            

            frameStart += FRAME_RATE;
            delay = frameStart - System.currentTimeMillis();
            if (delay > 0)
            
                Thread.sleep(delay);
            
        
    
    catch (InterruptedException exception) 

此外,如果您想消除持续运行的循环的轻微开销(对于大多数 inactive 线程),while 循环中的布尔值可以替换为 Semaphore 对象:

while (true)

    semaphore.acquire();  // Semaphore defined outside thread with 1 permit

    // INSERT YOUR LOOP CODE HERE 

    semaphore.release();

    frameStart += FRAME_RATE;
    delay = frameStart - System.currentTimeMillis();
    if (delay > 0)
    
        Thread.sleep(delay);
    

要在外部停止循环,请使用semaphore.acquire();重新启动它使用semaphore.release()

【讨论】:

以上是关于如何重新启动应用程序的更新循环的主要内容,如果未能解决你的问题,请参考以下文章

在 C++ 中满足某些条件(如果)后,如何重新启动 while 循环? [关闭]

如何在 python 中重新启动“for”循环? [复制]

如何在不重新启动活动的情况下更新 recyclerview(来自 sqlite 的数据)

如何更新/重新启动菜单?

在闪亮的 server.R 中更新数据框而不重新启动应用程序

重新启动时如何使这个 CSS 关键帧动画平滑?