如何从java运行多线程jython脚本? [英] Howto multithreaded jython scripts running from java?

查看:131
本文介绍了如何从java运行多线程jython脚本?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在用Java构建一个框架,它将监听事件,然后在Jython中处理它们。不同的事件类型将被发送到不同的脚本。

I'm constructing a framework in Java that will listen for events and then process them in Jython. Different event types will be sent to different scripts.

由于在调用PythonInterpreter.exec()时jython需要相当长的时间来编译脚本,因此我必须预编译脚本。我是按照以下方式进行的:

Since jython takes quite some time to compile the script when PythonInterpreter.exec() is called, I will have to pre-compile the scripts. I'm doing it the following way:

// initialize the script as string (would load it from file in final version)
String script = "print 'foo'";
// get the compiled code object
PyCode compiled = org.python.core.__builtin__.compile( script, "<>", "exec" );

PyCode编译对象将被推送到存储库并用作事件进入

The PyCode compiled object would be pushed to repository and used as events come in

PythonInterpreter pi = new PythonInterpreter();
pi.set( "variable_1", "value_1");
pi.set( "variable_x", "value_x");
pi.exec( compiled );

现在我的难题 - 可能会发生某些类型的多个事件同时发生 - 因此多个脚本实例同时运行。

Now for my conundrum - it might happen that there are multiple events of certain type happening at the same time - thus multiple instances of script running at the same time.

几乎所有脚本都可能保持短暂状态 - 最多100行,没有循环。数字和频率是完全随机的(用户生成的事件),每个事件类型可以是每秒0到大约200.

Almost all scripts would probably remain short-lived - up to 100 lines, no loops. Number and frequency is completely random (user generated events) and could be from 0 to about 200 per second per event type.

最好的方法是什么?我正在寻找一些可能性:

What would the best way to do it be? I'm looking at a few possibilities:


  1. 在触发事件点使用同步 - 这会阻止相同脚本的多个实例,但也会阻止事件发生不应该尽快处理

  2. 通过克隆原始PyCode对象以某种方式创建一个相同类型的脚本池 - 最大的问题可能是优化池大小

  3. 在需要时从父进程动态克隆脚本对象,然后在exec()完成时丢弃它 - 这样就会从编译中删除滞后但它仍然存在于克隆方法中

2号和3号的组合可能是最好的 - 创建动态池大小?

Probably the combination of number 2 and 3 would be the best - creating dynamic pool sizes?

所以,有什么想法吗? ;)

So, any thoughts? ;)

推荐答案

遗憾的是 PyCode 实例不是不可变的(类上有很多公共成员)。

It is a pity that PyCode instances aren't immutable (there are a lot of public members on the classes).

您可以使用以下代码预编译可重用的脚本:

You can precompile a reusable script using this code:

// TODO: generate this name
final String name = "X";
byte[] scriptBytes = PyString.to_bytes(script);
CompilerFlags flags = Py.getCompilerFlags();
ByteArrayOutputStream ostream = new ByteArrayOutputStream();
Module.compile(parser.parse(new ByteArrayInputStream(scriptBytes), "exec",
    "<>", flags), ostream, name, "<>", false, false, false, flags);
byte[] buffer = ostream.toByteArray();
Class<PyRunnable> clazz = BytecodeLoader.makeClass(name, null, buffer);
final Constructor<PyRunnable> constructor = clazz
    .getConstructor(new Class[] { String.class });

然后,您可以使用构造函数在需要时为脚本生成PyCode实例:

You can then use the constructor to produce PyCode instances for the script whenever you need one:

 PyRunnable r = constructor.newInstance(name);
 PyCode pc = r.getMain();

我是第一个承认这不是一个很好的做事方式而且可能会说话的人关于我对Jython的经验不足。但是,它比每次编译都要快得多。代码在Jython 2.2.1下运行,但不会在Jython 2.5下编译(也不会在你的代码下编译)。

I would be the first to admit that this is not a good way of doing things and probably speaks volumes about my inexperience with Jython. However, it is significantly faster than compiling every time. The code works under Jython 2.2.1, but won't compile under Jython 2.5 (nor will yours).

这篇关于如何从java运行多线程jython脚本?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆