Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/383.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/375.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Rhino和对javax.script.ScriptEngine的并发访问_Java_Javascript_Rhino - Fatal编程技术网

Rhino和对javax.script.ScriptEngine的并发访问

Rhino和对javax.script.ScriptEngine的并发访问,java,javascript,rhino,Java,Javascript,Rhino,我通过javax.scriptAPI使用Rhino 1.6r2。我知道Rhino引擎声称“引擎实现在内部是线程安全的,脚本可以并发执行,尽管脚本在一个线程上执行的效果可能对其他线程上的脚本可见。” 我想知道的是,在什么样的确切条件下,一个脚本执行的效果对另一个脚本执行是可见的?在我的代码中,我有时会重复使用ScriptEngine对象,但每次执行时,我都会创建一个新的SimpleBindings,并将其传递给eval(String,Bindings)。有了这种安排,内部状态是否有可能从一个执行泄

我通过
javax.script
API使用Rhino 1.6r2。我知道Rhino引擎声称“引擎实现在内部是线程安全的,脚本可以并发执行,尽管脚本在一个线程上执行的效果可能对其他线程上的脚本可见。”

我想知道的是,在什么样的确切条件下,一个脚本执行的效果对另一个脚本执行是可见的?在我的代码中,我有时会重复使用
ScriptEngine
对象,但每次执行时,我都会创建一个新的
SimpleBindings
,并将其传递给
eval(String,Bindings)
。有了这种安排,内部状态是否有可能从一个执行泄漏到另一个执行?如果是,怎么做


是的,JSR223没有指定脚本语言中的变量应该如何与给定的
绑定绑定。因此,实现者完全有可能选择在引擎实例中存储全局范围变量,并在评估脚本时重用它,即使给定不同的
绑定

例如,JRuby的JSR223绑定有一种模式是以这种方式工作的

import javax.script.ScriptContext;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import javax.script.SimpleScriptContext;

public class Jsr223Binding {


    private Jsr223Binding() throws ScriptException {
        System.setProperty("org.jruby.embed.localvariable.behavior", "transient");
        ScriptEngineManager manager = new ScriptEngineManager();
        ScriptEngine engine = manager.getEngineByName("jruby");
        ScriptContext ctx1 = new SimpleScriptContext();
        ScriptContext ctx2 = new SimpleScriptContext();
        engine.eval("$foo = 5\nputs $foo", ctx1);
        engine.eval("puts $foo", ctx2);
    }

    public static void main(String[] args) throws ScriptException {
        new Jsr223Binding();
    }
}

script包是线程安全的,但如果您的脚本不是线程安全的,则可能会出现并发问题。 脚本中的全局变量对所有线程都可见。因此,避免在javascript函数中使用全局变量

我现在遇到了这个问题。我的javascript如下所示:

function run(){
    regex = 0;
    regex += 1;
    return regex;
}
我在线程池中运行它(4)10000次,并打印结果

for (int i = 0; i <= 10000; i++){
        executor.submit(new Runnable() {
            @Override
            public void run() {
                try {
                    Double result = (Double) invocable.invokeFunction("run");
                    System.out.println(result);
                } catch (Exception e) {}
            }
        });
    }
我修改了答案,以表明如果在eval()函数中指定上下文,rhino脚本引擎的执行是完全线程安全的。此示例同时从5个不同线程调用javascript函数100次:

package samplethread;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

import javax.script.Bindings;
import javax.script.ScriptContext;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import javax.script.SimpleScriptContext;

public class JSRunner {

    private static final ScriptEngine engine;
    private static final ScriptEngineManager manager;

    private static final String script = "function fibonacci(num){\r\n" + 
            "  var a = 1, b = 0, temp;\r\n" + 
            "\r\n" + 
            "  while (num >= 0){\r\n" + 
            "    temp = a;\r\n" + 
            "    a = a + b;\r\n" + 
            "    b = temp;\r\n" + 
            "    num--;\r\n" + 
            "  }\r\n" + 
            "\r\n" + 
            "  return b;\r\n" + 
            "} \r\n" + 
            "var out = java.lang.System.out;\n" + 
            "n = 1;" +
            "while( n <= 100 ) {" +
            "   out.println(java.lang.Thread.currentThread().getName() +':'+ 'FIB('+ n +') = ' + fibonacci(n));" +
            "   n++;" +
            "   if (java.lang.Thread.interrupted()) {" +
            "       out.println('JS: Interrupted::'+Date.now());" +
            "       break;" +
            "   }" +
            "}\n"; 

    static {
        manager = new ScriptEngineManager();
        engine = manager.getEngineByName("JavaScript");
    }

    public static void main(final String... args) throws Exception {
        for(int i = 0;i<5;i++) {
            try {
                final Bindings b = engine.createBindings();
                final SimpleScriptContext sc = new SimpleScriptContext();
                sc.setBindings(b, ScriptContext.ENGINE_SCOPE);
                execWithFuture(engine, script,sc);
            }
            catch(Exception e) {
                e.printStackTrace();
            }
        }
    }

    private static void execWithFuture(final ScriptEngine engine, final String script,final ScriptContext sc) throws Exception {
        System.out.println("Java: Submitting script eval to thread pool...");
        ExecutorService single = Executors.newSingleThreadExecutor();
        Callable<String>  c = new Callable<String>() {

            public String call() throws Exception {
                String result = null;
                try {
                    engine.eval(script,sc);         
                } catch (ScriptException e) {
                    result = e.getMessage();
                } 
                return result;
            }
        };

        single.submit(c);
        single.shutdown();
        System.out.println("Java: ...submitted.");
    }   
}
package-samplethread;
导入java.util.concurrent.Callable;
导入java.util.concurrent.ExecutorService;
导入java.util.concurrent.Executors;
导入java.util.concurrent.Future;
导入javax.script.Bindings;
导入javax.script.ScriptContext;
导入javax.script.ScriptEngine;
导入javax.script.ScriptEngineManager;
导入javax.script.ScriptException;
导入javax.script.SimpleScriptContext;
公共类JSRunner{
私有静态脚本引擎;
私有静态最终脚本引擎管理器;
private static final String script=“函数fibonacci(num){\r\n”+
变量a=1,b=0,临时;\r\n“+
“\r\n”+
“while(num>=0){\r\n”+
“temp=a;\r\n”+
“a=a+b;\r\n”+
“b=temp;\r\n”+
“num——;\r\n”+
“}\r\n”+
“\r\n”+
“返回b;\r\n”+
“}\r\n”+
“var out=java.lang.System.out;\n”+
“n=1;”+

“一会儿(n你是在绑定同一个对象吗?如果我绑定同一个对象进行多次执行,那么显然所有人都可以看到。但不,我没有这么做。那么你到底想弄清楚什么?如果你对不同的绑定对象使用不同的绑定,你还关心哪些状态?@wort-I是t暗示更多由脚本创建或修改的状态,而不是从Java传递到脚本中。如果我在脚本中声明一个全局变量,该变量的范围是什么?如果我修改某个内置全局变量会发生什么?这些是由javax.script API指定的,还是由引擎实现者指定的?这是您正在寻找的吗对于?您所说的根本不是真的。如果为同一脚本引擎实例创建单独的脚本上下文,并指定适当的范围(引擎范围),则不会出现此问题。
package samplethread;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

import javax.script.Bindings;
import javax.script.ScriptContext;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import javax.script.SimpleScriptContext;

public class JSRunner {

    private static final ScriptEngine engine;
    private static final ScriptEngineManager manager;

    private static final String script = "function fibonacci(num){\r\n" + 
            "  var a = 1, b = 0, temp;\r\n" + 
            "\r\n" + 
            "  while (num >= 0){\r\n" + 
            "    temp = a;\r\n" + 
            "    a = a + b;\r\n" + 
            "    b = temp;\r\n" + 
            "    num--;\r\n" + 
            "  }\r\n" + 
            "\r\n" + 
            "  return b;\r\n" + 
            "} \r\n" + 
            "var out = java.lang.System.out;\n" + 
            "n = 1;" +
            "while( n <= 100 ) {" +
            "   out.println(java.lang.Thread.currentThread().getName() +':'+ 'FIB('+ n +') = ' + fibonacci(n));" +
            "   n++;" +
            "   if (java.lang.Thread.interrupted()) {" +
            "       out.println('JS: Interrupted::'+Date.now());" +
            "       break;" +
            "   }" +
            "}\n"; 

    static {
        manager = new ScriptEngineManager();
        engine = manager.getEngineByName("JavaScript");
    }

    public static void main(final String... args) throws Exception {
        for(int i = 0;i<5;i++) {
            try {
                final Bindings b = engine.createBindings();
                final SimpleScriptContext sc = new SimpleScriptContext();
                sc.setBindings(b, ScriptContext.ENGINE_SCOPE);
                execWithFuture(engine, script,sc);
            }
            catch(Exception e) {
                e.printStackTrace();
            }
        }
    }

    private static void execWithFuture(final ScriptEngine engine, final String script,final ScriptContext sc) throws Exception {
        System.out.println("Java: Submitting script eval to thread pool...");
        ExecutorService single = Executors.newSingleThreadExecutor();
        Callable<String>  c = new Callable<String>() {

            public String call() throws Exception {
                String result = null;
                try {
                    engine.eval(script,sc);         
                } catch (ScriptException e) {
                    result = e.getMessage();
                } 
                return result;
            }
        };

        single.submit(c);
        single.shutdown();
        System.out.println("Java: ...submitted.");
    }   
}