2015-01-01 23 views
5

È possibile riutilizzare lo stesso motore Nashorn e lo stesso JavaScriptObject, che risulta come la valutazione di una funzione JS, per tutte le richieste di servlet, se la funzione non modifica alcun oggetto condiviso ma utilizza solo gli argomenti dato con la chiamata? Guarda il seguente esempio:È una funzione valutata in Nashorn riutilizzabile da diversi thread?

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); 
    } 
} 

Questa thread è sicura? Si tratta di un follow-up a Reuse Nashorn ScriptEngine in Servlet

Edit: Non sono sicuro che differenza questo rende per la questione a portata di mano, ma di concentrarsi sulla questione più interessante, in quali circostanze una chiamata a un valutato js-function è thread save, ho reso tutti i campi finali ora. Quindi il codice è:

public class MyServlet extends HttpServlet { 

final private ScriptEngineManager factory; 
final private ScriptEngine engine; 
final private ScriptObjectMirror script; 

public MyServlet() { 
    factory = new ScriptEngineManager(); 
    engine = factory.getEngineByName("nashorn"); 
    ScriptObjectMirror _script = null; 
    try { 
     _script = (ScriptObjectMirror) engine.eval("function(writer) {writer.print('Hello, World!');}"); 
    } catch (ScriptException ex) { 
     Logger.getLogger(MyServlet.class.getName()).log(Level.SEVERE, null, ex); 
    } 
    script = _script; 
} 

@Override 
public void init() throws ServletException { 
} 

@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); 
    } 
} 

risposta

1

Nessuno dei tuoi variabili di istanza sono safely published, così che è un grande "no" proprio lì. Inoltre nessuno dei documentation dice che le classi che usi sono thread-safe, quindi senza ulteriore documentazione che dice in modo diverso devi presumere che non siano thread-safe.

Risposta: no.

+0

Potresti essere più specifico sui problemi di concorrenza che vedi? Il metodo init del servlet non viene invocato contemporaneamente. Quindi non ci dovrebbero essere problemi con il motore di script. Lo script valutato può essere invocato contemporaneamente, ma non fa riferimento a nessuna risorsa condivisa. Perché pensi che questo sia problematico? – Gregor

+0

Questa potrebbe essere una domanda migliore per il sito gemello di Stackoverflow, programmers.stackexchange.com. Citerò brevemente: c'è sicuramente una risorsa condivisa in 'doGet()', è la variabile 'script'. Per quanto riguarda 'init()', puoi puntare a qualsiasi documentazione JEE che dice che c'è qualche sincronizzazione tra 'init()' e 'doGet()'? Questo è roba di base, hai davvero bisogno di saperne di più sul multithreading se non riesci a vedere questi problemi. – markspace

+1

Come ho scritto: lo script è invocato contemporaneamente. È condiviso Ma le variabili condivise non sono necessariamente necessarie. lo script stesso non scrive su nessuna risorsa condivisa, poiché la richiesta servlet è per thread. Quindi quello di cui ho bisogno è una risposta alla domanda, ciò che è implicato nel chiamare un js-script. La documentazione di Nashorn tace su questo. Per quanto riguarda il metodo init, puoi vedere che è vuoto nel mio esempio migliorato sopra. – Gregor

Problemi correlati