【问题标题】:Nashorn in thread safe mannerNashorn 以线程安全的方式
【发布时间】:2015-12-08 20:39:46
【问题描述】:

下面我分享了我的代码,我在其中尝试使用线程安全的 Nashorn 作为脚本引擎来评估简单的数学公式。公式类似于“a*b/2”,其中 a 和 b 将从地图对象中提取。

public class EvaluateFormulas {

@Autowired
NashornThreadPool pool;

private ScriptEngineManager factory;
private ScriptEngine engine;
private ScriptContext context;

@PostConstruct
public void setup() {
    factory = new ScriptEngineManager();
    engine = factory.getEngineByName("nashorn");
    context = engine.getContext();
}

public void evaluate() {
    pool.getThreadPoolExecutor().submit(new Runnable() {
        @Override
        public void run() {
            Double result;
            Bindings bind = engine.createBindings();
            bind.putAll(map);
            context.setBindings(bind, ScriptContext.GLOBAL_SCOPE);
            try {
                result = (Double) engine.eval(formula);
            } catch (ScriptException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    });
}   
}

我需要知道这种方法是否有助于使 Nashorn 线程对这个用例安全。我在 Attila 的 answer 中读到,我们可以在线程之间共享脚本引擎对象,因为它们是线程安全的。

对于绑定和评估,因为我们正在为每次执行 evaluate 创建新线程,并且每个线程都有自己的绑定对象引用。那么总的来说,这个实现会是线程安全的吗?

【问题讨论】:

    标签: java multithreading thread-safety nashorn scriptengine


    【解决方案1】:

    我认为这不是线程安全的,因为您正在更改绑定,而另一个线程可能正在执行代码。您实际上不需要这样做;您可以创建一个全新的上下文,然后在该上下文中评估脚本。我会这样做:

    public void evaluate() {
        pool.getThreadPoolExecutor().submit(new Runnable() {
            @Override
            public void run() {
                Double result;
    
                ScriptContext myContext = new SimpleScriptContext();
                Bindings bindings = engine.createBindings();
                bindings.putAll(map);
                myContext.setBindings(bindings, ScriptContext.ENGINE_SCOPE);
    
                try {
                    result = (Double) engine.eval(formula, myContext);
                } catch (ScriptException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        });
    }
    

    现在每个脚本都在自己的上下文中进行评估。

    【讨论】:

    • 我为每个执行使用单独的 Binding 对象,例如 SimpleBindings simpleBindings = new SimpleBindings(); 然后 engine.eval(script, simpleBindings); 。我完全跳过了使用上下文。那个线程安全吗?
    • 我不完全确定,但我猜不是因为它会使用相同的上下文。
    猜你喜欢
    • 1970-01-01
    • 2011-08-30
    • 2020-06-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-16
    • 1970-01-01
    相关资源
    最近更新 更多