Java 在NetLogo扩展中处理作业线程和GUI工作区

Java 在NetLogo扩展中处理作业线程和GUI工作区,java,multithreading,api,netlogo,Java,Multithreading,Api,Netlogo,我正在开发一个可以同时打开多个模型的扩展。模型可以动态打开和关闭。模型作为litespace打开,以便显示小部件等。每当你创建一个新的LiteWorkspace,它就会启动一个JobThread和Lifeguard。问题在于,关闭GUIWorkspace(LiteWorkspace的父类)并不会杀死它的救生员或作业线程 可能的解决办法: 理想的解决方案是让所有模型共享一个JobThread,因为这将消除线程数作为一个模型可以运行的上限。这样做也有一定的性能优势。这有可能吗?此解决方案仍然需要能够

我正在开发一个可以同时打开多个模型的扩展。模型可以动态打开和关闭。模型作为
litespace
打开,以便显示小部件等。每当你创建一个新的
LiteWorkspace
,它就会启动一个
JobThread
Lifeguard
。问题在于,关闭
GUIWorkspace
LiteWorkspace
的父类)并不会杀死它的
救生员
作业线程

可能的解决办法:

  • 理想的解决方案是让所有模型共享一个
    JobThread
    ,因为这将消除线程数作为一个模型可以运行的上限。这样做也有一定的性能优势。这有可能吗?此解决方案仍然需要能够杀死
    救生员

  • 下一步当然是能够杀死线程

  • 作为最后一种手段,我们可以在
    GUIWorkspace
    s周围保留一个池。当用户关闭一个模型时,它会被抛出回池中。然后,当用户加载一个新模型并且池中有东西时,我们只需重用其中一个
    GUIWorkspace
    s。这将允许我们打开与2相同数量的模型。唯一的缺点是打开一个新模型(比如全新的,从“文件”菜单或其他什么)仍然不会杀死线程,所以这是一个永久性的资源包袱。实际上,出于性能原因,我们可能不得不建立一个池,但如果能够在某个时候真正释放资源,那就太好了


  • 解决方案1不可行;每个工作区一个作业线程的假设深深地嵌入到代码中

    要使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)
    ...
    
    /Applications/NetLogo 5.0.5%scala29-Yrepl sync-classpath NetLogo.jar
    欢迎使用Scala版本2.9.3(Java热点(TM)64位服务器虚拟机,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_
    导入collection.JavaConverters_
    scala>Thread.getAllStackTraces().keySet.asScala.foreach(println)
    线程[作业线程,4,主线程]
    线程[救生员,6,主]
    ...
    scala>ws.jobManager.haltPrimary()
    scala>ws.jobManager.die()
    scala>import-util.Try
    导入util.Try
    scala>用于{
    thread thread.getAllStackTraces().keySet.asScala.foreach(println)
    ...
    
    (注意,我已经用Scala回答了这个问题;到Java的转换留给读者。用于访问内部类的外部实例的反射内容来自于。)


    一个以更简洁的方式添加代码实现
    GUIWorkspace.dispose()
    的请求将是受欢迎的。

    工作得很好!谢谢!这个$0
    非常聪明。