关于python:在Jython中处理密集型事件动作

Handling Processing-Intensive Event-Actions in Jython

我有一些长期的过程,这些过程必须在我创建的Jython GUI中给定的按钮按下或其他事件下发生。

在这种情况下,最好的选择似乎是创建一个单独的线程,以便在事件发生时运行被调用的方法/函数。

做这个的最好方式是什么? 导入线程,并拥有一个在actionPerformed时初始化并运行的类? 使用invokelater吗? 似乎有很多方法可以解决此问题,但是在Jython-Swing环境中是否会表现最佳并成为"最快"的?

1
2
3
4
5
6
start = JButton("Analyze", actionPerformed = self.do_analysis )

def do_analysis(self):
    ...
    Large Time Consuming Task
    ...


我不是100%肯定jython会遇到同样的问题,但是在C Python中,您会遇到GIL或Global Interpreter Lock的问题。这将意味着,当您的后台线程正在运行时,GUI线程将无法启动(即使已排队等待在另一个内核上运行)。您单击一个按钮,没有任何反应:(

为了解决这个问题,我将长时间运行的流程分为可以在事件上运行的几个步骤,然后将事件排队,以便在当前步骤结束时开始下一步。然后,如果需要,GUI将能够在步骤之间运行。您执行的步骤越短,GUI的响应就越快-50ms至100ms应该可以。

这种方法具有很好的副作用,您无需担心线程,锁定,消息队列或其他任何问题。您可以尝试将它们添加到GUI,但是GUI事件和线程可能会发生冲突,从而导致一些非常奇怪且难以调试的错误。

至于"最快",这对于较短的后台任务来说可能是最低的开销。如果您创建一个新进程来运行后台任务(Windows中的开销非常大),则由于它具有自己的核心,因此它将运行得更快,但是启动/停止开销很高。


在这种情况下,通过记住Jython在JVM上运行,您将获得最佳结果。 Jython拥有对Java类的完全访问权限,因此请使用Java线程API来设置单独的计算线程。而且,如果CPU负载足够高,以至于使用更多的内核会有所帮助,那么Java(jvm)将自行解决。

在某些情况下,随着进程的长时间运行,人们使用jstack -l获取正在运行的线程的nids,然后使用taskset设置CPU亲和力。 JVM nid以十六进制表示,是与线程相对应的Linux进程的PID。其他操作系统可能具有类似的功能。

通常,除了使Jython多线程外,没有必要做任何其他事情。如果使用Python线程模块,则无权访问完整的Java线程功能集,但实际上使用了JVM线程。只要记住要限制对全局变量的访问,否则最终将重新创建全局解释器锁。队列模块可以提供帮助。