2014-11-03 70 views
0

正如在documentation中所提到的,我在后台运行一个后台线程,无限次地使用1个实例进行一些连续的后台处理。在google appengine后台运行只有一个后台线程

import com.google.appengine.api.ThreadManager; 
import java.util.concurrent.AtomicLong; 

AtomicLong counter = new AtomicLong(); 

Thread thread = ThreadManager.createBackgroundThread(new Runnable() { 
    public void run() { 
    try { 
     while (true) { 
     counter.doStuff() 
     Thread.sleep(10); 
     } 
    } catch (InterruptedException ex) { 
     throw new RuntimeException("Interrupted in loop:", ex); 
    } 
    } 
}); 
thread.start(); 

我已将此代码绑定到_ah/start端点,以便在实例启动后执行它。然而,当在本地服务器上运行时,我发现_ah/start请求在运行时会多次出现,并启动多个此类线程。我一次只需要一个线程来减少后台处理中的争用。

有什么办法抓住现有的bg线程并检查它的运行是否可以避免新的线程创建?

更新 上传这个代码到云后,我还观察到,每次_ah /启动是在后台调用它产生一个新的线程为_ah /背景端点的一部分,并保持运行。以这种方式,如果我们不能阻止较早的线程,那么会有很多线程一起运行。

+0

一种方法在类成员变量中标记时间,并在尝试创建第二个线程时检查它是否是最近的。 – SoulMan 2014-11-03 11:45:18

回答

1

后端实例可能不是您所需要的。

这是事情:你想在服务器上运行无限处理。后端并不意味着这一点。您可能需要考虑在计算引擎上为该特定情况分配虚拟机。

后台用于在后台运行长操作。这些操作通常由用户请求。你的情况是不同的,这就是为什么我会考虑虚拟机场景。

无论如何,特别是针对您遇到的问题,运行线程的实例实际上并未接收多个_ah/start请求。每个实例只收到其中一个请求。但是,系统试图用多个_ah/start请求分离多个实例。我不知道为什么,但显然有些事情是要求后端多次出现。

你可以做什么来避免内存中的多个线程,只要一个线程运行,就在Memcache中添加一个标志(这是所有后端共享的)。每次线程启动时,检查该标志是否不存在。如果有,请不要启动线程。

确保您还实施_ah/stop请求以从memcache中删除该标志。

希望这会有所帮助。

+0

谢谢。是的,我最终会去GCE一点点,但只是好奇这里发生了什么。你是对的_ah/start在云中只被调用一次,即使是单个后端(在不同的端口上模拟),该开发服务器也可以多次调用该端点。现在我可能需要一种机制来确保一个新线程运行,以防一个线程由于某种原因突然停止。 – SoulMan 2014-11-04 03:58:07

+0

另外,正如我在问题的评论中提到的,我可以依靠类成员变量来设置标志。我认为将会有一个这样的类实例被注入其冲刺。 – SoulMan 2014-11-04 04:02:14

+0

如果你有两个实例在运行(每个实例都在处理一个线程),那么第二个实例的类变量将不可见(它们将在不同的处理器中运行)。 Memcache是​​您唯一的解决方案。您的国旗可以是每3秒左右更新一次的时间戳。当你得到一个_ah /开始检查标志是否最近被更新了,如果没有,你可以开始你的线程。如果它已更新,则知道还有另一个线程已经运行。 – svpino 2014-11-05 13:43:13