我正在开发一个可同时打开多个模型的扩展。可以动态打开和关闭模型。模型以LiteWorkspace的形式打开,以便显示小部件等。每当创建新的LiteWorkspace时,它都会启动JobThreadLifeguard。问题是关闭GUIWorkspace(父类LiteWorkspace)不会杀死其LifeguardJobThread

可能的解决方案:


理想的解决方案是让所有模型共享一个JobThread,因为这将删除线程数量,以限制一个模型可以运行多少个模型。这样做也会带来一定的性能优势。有机会吗?此解决方案仍然需要能够杀死Lifeguard
下一步当然是能够杀死线程。
作为最后的选择,我们可以保留GUIWorkspace个池。当用户关闭模型时,模型将被扔回到池中。然后,当用户加载新模型并且池中有东西时,我们仅重用这些GUIWorkspace之一。这将允许我们打开与2相同数量的模型。唯一的缺点是,打开新模型(例如,从文件菜单或其他菜单中全新打开)仍然不会杀死线程,因此存在这种永久资源负担闲逛。实际上,出于性能方面的考虑,我们实际上可能必须建立一个池,但是实际上能够在某个时候释放资源将是非常好的。

最佳答案

解决方案1不可行;每个工作区一个JobThread的假设已深深地嵌入到代码中。

要使JobThread消失,这应该足够了:

workspace.jobManager.haltPrimary()
workspace.jobManager.die()


要使GUIWorkspace.Lifeguard线程消失,我们只需要在其上调用interrupt()即可,但是即使仅获得对该引用的引用也不是那么容易。这是显示成功尝试的笔录:

/Applications/NetLogo 5.0.5 % scala29 -Yrepl-sync -classpath NetLogo.jar
Welcome to Scala version 2.9.3 (Java HotSpot(TM) 64-Bit Server VM, Java 1.7.0_51).

scala> val applet = new org.nlogo.lite.Applet
applet: org.nlogo.lite.Applet = ...

scala> applet.init()
...

scala> val ws = applet.panel.workspace: org.nlogo.window.GUIWorkspace
ws: org.nlogo.window.GUIWorkspace = org.nlogo.lite.LiteWorkspace@69cafecd

scala> import collection.JavaConverters._
import collection.JavaConverters._

scala> Thread.getAllStackTraces().keySet.asScala.foreach(println)
Thread[JobThread,4,main]
Thread[Lifeguard,6,main]
...

scala> ws.jobManager.haltPrimary()

scala> ws.jobManager.die()

scala> import util.Try
import util.Try

scala> for {
         thread <- Thread.getAllStackTraces().keySet.asScala
         if thread.getName == "Lifeguard"
         outer = Try{ val field = thread.getClass.getDeclaredField("this$0")
                      field.setAccessible(true)
                      field.get(thread) }
         if outer.toOption == Some(ws)
       } {
         thread.interrupt()
         thread.join()
       }
Success(org.nlogo.lite.LiteWorkspace@69cafecd)

scala> Thread.getAllStackTraces().keySet.asScala.foreach(println)
...


(请注意,我已经在Scala中回答了;转换为Java留给了读者。用于访问内部类的外部实例的反射内容来自https://stackoverflow.com/a/763617/86485。)

将添加以更简洁的方式添加实现GUIWorkspace.dispose()的代码的请求请求。

10-03 00:14