java脚本引擎Groovy并发控制

ScriptEngine是线程安全的,自身没有线程问题,但是变量作用域(Bindings)存在线程问题。一般计算时,如果不考虑线程,都是使用的默认Bindings:

java脚本引擎Groovy并发控制_第1张图片

通过源码可以看到,如果不指定Bindings,默认使用内置的Bindings。

这就会导致多线程存在问题,一个线程的变量可能会被另一个线程覆盖掉,导致计算结果出错。所有为了保证不同线程变量作用域相互独立,可以根据线程号来创建Bindings:

    /**
     * 得到当前线程号
     */
    public int getCurrentThread(){
        String threadName = Thread.currentThread().getName().replace("Thread-","");
        return NumberUtil.saveToInteger(threadName,1);
    }
private Map bindingMap = new HashMap<>(50);

首先定义一个全局map,用来保存线程号和Bindings作用域的映射,可以不用每次计算都去创建新的Bindings,使同一个线程多次计算时,只创建一次Bindings。

    /**
     * 根据线程号返回binding,不存在时创建
     * @param threadNum     线程号
     */
    public Bindings getEngineBinding(int threadNum){
        return bindingMap.computeIfAbsent(threadNum, k -> engine.createBindings());
    }

该线程用完脚本引擎后,必须手动移除Bindings,否则不久就可能导致内存溢出。

一般建议将cleanEngineScope()放在finally语句块中执行,保证异常也一定会执行

    /**
     * 根据线程号清除Binding
     * @param threadNum     线程号
     */
    public void cleanEngineScope(int threadNum){
        bindingMap.remove(threadNum);
    }

完整代码:http://download.csdn.net/download/qq_36635569/12077855

你可能感兴趣的:(脚本引擎,java)