我的程序使用Java Scripting API并且可以同时评估一些脚本.他们不使用共享脚本对象,绑定或上下文,但可以使用相同ScriptEngine和CompiledScript对象.我看到Java 8中的Oracle Nashorn实现不是多线程的,ScriptEngineFactory.getParameter('THREADING')返回null文档所说的内容:
引擎实现不是线程安全的,不能用于在多个线程上并发执行脚本.
这是否意味着我应该ScriptEngine为每个线程创建一个单独的实例?此外,文档没有说明CompiledScript并发使用,但:
每个CompiledScript都与ScriptEngine相关联
可以假设CompiledScript线程安全依赖于相关ScriptEngine,即我应该CompiledScript为Nashorn的每个线程使用单独的实例.
如果我应该,对于这个(我认为非常常见的)案例,使用ThreadLocal,池或其他什么是适当的解决方案?
final String script = "...";
final CompiledScript compiled = ((Compilable)scriptEngine).compile(script);
for (int i=0; i<50; i++) {
Thread thread = new Thread () {
public void run() {
try {
scriptEngine.eval(script, new SimpleBindings ()); //is this code thread-safe?
compiled.eval(new SimpleBindings ()); //and this?
}
catch (Exception e) { throw new RuntimeException …Run Code Online (Sandbox Code Playgroud) 如果函数不更改任何共享对象但仅使用给定的参数,是否可以重用同一个Nashorn引擎和同一个JavaScriptObject(对于所有servlet请求,作为JS函数的评估)电话?请看以下示例:
public class MyServlet extends HttpServlet {
private ScriptEngineManager factory;
private ScriptEngine engine;
private ScriptObjectMirror script;
@Override
public void init() throws ServletException {
try {
factory = new ScriptEngineManager();
engine = factory.getEngineByName("nashorn");
script = (ScriptObjectMirror)engine.eval("function(writer) {writer.print('Hello, World!');}");
} catch (ScriptException ex) {
Logger.getLogger(MyServlet.class.getName()).log(Level.SEVERE, null, ex);
}
}
@Override
public void doGet(HttpServletRequest req, HttpServletResponse res) throws IOException {
try (PrintWriter writer = res.getWriter()) {
script.call(null, writer);
writer.close();
} catch (IOException ex) {
Logger.getLogger(MyServlet.class.getName()).log(Level.SEVERE, null, ex);
}
}
Run Code Online (Sandbox Code Playgroud)
这是线程安全的吗?这是在Servlet中重用Nashorn ScriptEngine的后续内容 …
如果以下代码可以在多线程应用程序中运行,您能帮我解决吗?
这是我的Java脚本,将由Nashorn评估
var Thread = Java.type("java.lang.Thread");
var referenceNumberValid = "0000";
var referenceNumberInvalid = "0001";
function validate (parameters) {
var isValid = false;
var statusCode;
var referenceNumber = parameters.referenceNumber;
var validateNumber = referenceNumber.substr(0, 7);
var sum = 0;
for (ctr = 0; ctr < validateNumber.length; ctr++) {
sum += parseInt(validateNumber.substr(ctr, 1));
}
var checkDigit = sum % 10;
isValid = parseInt(referenceNumber.substr(7, 1)) == checkDigit;
statusCode = isValid ? referenceNumberValid : referenceNumberInvalid;
print("Thread: " + Thread.currentThread().getId() + ", isValid: " + isValid …Run Code Online (Sandbox Code Playgroud)