玩!框架:在多个请求上重用实例

时间:2011-08-16 14:45:56

标签: java playframework

我使用Play开发应用程序!大量使用javax.script包的框架,包括ScriptEngine。由于ScriptEngines的创建成本很高,因此在多个请求中使用它们是有意义的(我不打算创建多个ScriptEngines,每个线程一个 - 至少我不会一遍又一遍地为每个请求创建ScriptEngines)。

我认为这个案例并不局限于ScriptEngines,框架中可能有一些我不知道处理这种情况的东西。

感谢您的任何想法! 马拉克斯

2 个答案:

答案 0 :(得分:2)

Play是无状态的,因此没有“会话式”机制将对象链接到用户。您可能有两种选择:

使用缓存。使用唯一ID将ScriptEngine存储在缓存中,并添加一个方法来检查它是否仍然存在。类似的东西:

public static Engine getScriptEngine(Long userId) {
     String key = "MY_ENGINE" + userId;
     ScriptEngine eng = (ScriptEngine) Cache.get(key);
     if(eng == null) {
        eng = ScriptEngine.create(); 
        Cache.put(key, eng);
     }
     return eng;
}

或者创建一个包含ScriptEngine静态实例的单例对象,以便在服务器启动后始终存在。

我想说Cache 1是最好的方法。

编辑:关于你的评论,这取决于具体情况:

  1. 如果您希望在唯一用户的多个请求中重用Engine(即每个用户都有自己的ScriptEngine),则缓存方法可用作缓存将Engine链接到用户ID。这也可以解决任何线程问题。
  2. 否则,如果要在多个用户的多个请求中重用它,静态方法是一种更好的方法。但正如您所提到的那样,在Play或任何系统中访问都不是线程安全的。
  3. 我认为你最好的选择是与他们异步工作。我不知道你将如何使用ScriptEngines,但尝试做这样的事情:

    • 根据请求,在标记ScriptEngine处理请求的数据库的表中存储条目
    • 在同一请求中,启动asynchronous作业(或每30秒运行一次)
    • 作业将读取表格的第一个条目,删除它,执行任务,将答案返回给用户。该作业可能有一个ScriptEngine池可供使用。
    • 由于在当前工作正在工作时不会再次启动工作,如果您有需求,工作将永远不会停止工作。如果它这样做意味着您当时不需要引擎,它们将根据需要重新创建。

    通过这种方式,您可以线性地使用池,忽略线程问题。如果你不能这样做,那么你需要修复ScriptEngine的线程安全性,因为你不能假装在一个生成多个线程的服务器environemnt中共享一个它不是线程安全的对象:)

答案 1 :(得分:0)

为什么不实现脚本池?因此,每个请求都以与JDBC-Connection-Pool相同的方式从池中获取实例。 但要确保脚本引擎是无状态的。

相关问题