utilizando temporizador reloj proyectos programas paso hilos hacer ejemplos cronometro contador con como java multithreading nashorn jsr223

java - temporizador - ¿Debo usar una instancia separada de ScriptEngine y CompiledScript por cada hilo?



reloj java hilos (4)

Ejemplo de código para la respuesta de @ attilla

  1. mi código js es algo como esto:

    var renderServer = function renderServer(server_data) { //your js logic... return html_string. }

  2. código java:

    public static void main(String[] args) { String jsFilePath = jsFilePath(); String jsonData = jsonData();

    try (InputStreamReader isr = new InputStreamReader(new URL(jsFilePath).openStream())) { NashornScriptEngine engine = (NashornScriptEngine) new ScriptEngineManager().getEngineByName("nashorn"); CompiledScript compiledScript = engine.compile(isr); Bindings bindings = engine.createBindings(); compiledScript.eval(bindings); ScriptObjectMirror renderServer = (ScriptObjectMirror) bindings.get("renderServer"); String html = (String) renderServer.call(null, jsonData); System.out.println(html); } catch (Exception e) { e.printStackTrace(); } }

tenga cuidado al usar el método renderServer en un entorno de subprocesos múltiples, ya que los enlaces no son seguros para subprocesos. Una solución es usar varias instancias de renderServer con renderServer de renderServer reutilizables. Estoy usando org.apache.commons.pool2.impl.SoftReferenceObjectPool , que parece estar funcionando bien para mi caso de uso.

Mi programa utiliza la API de Java Scripting y puede evaluar algunos scripts simultáneamente. No usan objetos de script compartidos, enlaces o contexto, pero pueden usar los mismos objetos ScriptEngine y CompiledScript . Veo que la implementación de Oracle Nashorn en Java 8 no es multiproceso, ScriptEngineFactory.getParameter(''THREADING'') devuelve un null sobre el que dice la documentación:

La implementación del motor no es segura para subprocesos y no se puede usar para ejecutar scripts simultáneamente en múltiples subprocesos.

¿Significa que debería crear una instancia separada de ScriptEngine para cada hilo? Además, la documentación no dice nada sobre el uso concurrente de CompiledScript pero:

Cada CompiledScript está asociado con un ScriptEngine

Se puede suponer que la seguridad de subprocesos de CompiledScript depende de ScriptEngine relacionado, es decir, debería usar una instancia de CompiledScript separada para cada subproceso con Nashorn.

Si debo, ¿cuál es la solución adecuada para este caso (creo que es muy común), usando ThreadLocal , un grupo u otra cosa?

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 (e); } } }; threads.start(); }


La respuesta aceptada engañará a muchas personas.

En breve:

  • NashornScriptEngine NO es seguro para subprocesos
  • Si NO utiliza enlaces globales, la parte sin estado puede ser segura para subprocesos

Puede compartir un ScriptEngine y objetos CompiledScript entre hilos. Son a prueba de hilos. En realidad, debe compartirlos, ya que una instancia de un solo motor es un soporte para un caché de clase y para las clases ocultas de los objetos JavaScript, por lo que al tener solo uno reduce la compilación repetida.

Lo que no puedes compartir son los objetos de Bindings . El objeto de enlaces corresponde básicamente al objeto Global del entorno de tiempo de ejecución de JavaScript. El motor comienza con una instancia de enlaces predeterminada, pero si lo usa en un entorno multiproceso, debe usar engine.createBindings() para obtener un objeto de enlaces separado para cada hilo, su propio global, y evaluar las secuencias de comandos compiladas en él. De esa manera, configurará ámbitos globales aislados con el mismo código. (Por supuesto, también puede agruparlos o sincronizarlos, solo asegúrese de que nunca haya más de un hilo trabajando en una instancia de enlaces). Una vez que evaluó la secuencia de comandos en los enlaces, puede invocar eficientemente las funciones que definió con ((JSObject)bindings.get(fnName).call(this, args...)

Si debe compartir el estado entre subprocesos, al menos intente que no sea mutable. Si sus objetos son inmutables, también podría evaluar el script en una única instancia de Bindings y luego usarlo en todos los hilos (invocando funciones libres de efectos secundarios). Si es mutable, tendrá que sincronizar; ya sea los enlaces completos, o también puede usar var syncFn = Java.synchronized(fn, lockObj) API JS específica de Nashorn para obtener versiones de funciones JS que se sincronizan en un objeto específico.

Esto presupone que comparte enlaces individuales entre hilos. Si desea que varios enlaces compartan un subconjunto de objetos (por ejemplo, al poner el mismo objeto en múltiples enlaces), nuevamente, tendrá que lidiar de alguna manera para garantizar que el acceso a los objetos compartidos sea seguro para los hilos.

En cuanto al parámetro THREADING que devuelve nulo : sí, inicialmente planeamos no hacer que el motor fuera seguro (diciendo que el lenguaje en sí mismo no es seguro), por lo que elegimos el valor nulo. Es posible que necesitemos reevaluar eso ahora, ya que mientras tanto lo hicimos para que las instancias del motor sean seguras para subprocesos, solo el alcance global (enlaces) no es (y nunca lo será, debido a la semántica del lenguaje JavaScript).


ScriptEngine para Nashorn no es ScriptEngine para subprocesos. Esto se puede verificar llamando a ScriptEngineFactory.getParameter("THREADING") de ScriptEngineFactory para Nashorn.

El valor devuelto es nulo, lo que según java doc significa que no es seguro para subprocesos.

Nota: Esta parte de la respuesta se dio primero here . Pero volví a comprobar los resultados y a mí mismo.

Esto también nos da la respuesta para CompiledScript . Según java doc, un CompiledScript está asociado a un ScriptEngine .

Por lo tanto, en Nashorn ScriptEngine y CompiledScript no deben ser utilizados por dos hilos al mismo tiempo .