2015-01-01 18 views
5

Bir ve aynı Nashorn motoru ile bir ve aynı JavaScriptObject öğesinin yeniden kullanılabilmesi, bir JS işlevinin değerlendirilmesi, tüm sunucu istekleri için, işlev herhangi bir paylaşılan nesneyi değiştirmiyorsa ancak yalnızca argümanlar kullanıyorsa yeniden kullanılabilir mi? çağrı ile verilen? Aşağıdaki örneğe bakın:Farklı ipliklerden tekrar kullanılabilen Nashorn'da değerlendirilen bir işlev midir?

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

Bu iş parçacığı güvenli mi? Bu bir takip olduğunu Reuse Nashorn ScriptEngine in Servlet

Düzenleme: Bu el altında soru için kılan fark emin değilim, ama hangi koşullar altında bir çağrı bir değerlendirildiğinde, daha ilginç bir soru odaklanmak js işlevi iş parçacığı kaydet, şimdi tüm alanları final yaptım. Yani kod şudur: örnek değişkenleri

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

cevap

1

Yok safely published, böylece orada "hayır" büyüktür vardır. Ayrıca, documentation'un hiçbiri kullandığınız sınıfların iş parçacığı için güvenli olmadığını, bu yüzden başka bir belgeyi kullanmadan, farklı bir deyişle, iş parçacığının güvenli olmadıklarını varsaymanız gerektiğini söylüyor.

Yanıt: nope.

+0

Gördüğünüz eşzamanlılık sorunları hakkında daha spesifik olabilir misiniz? Servletin init yöntemi eşzamanlı olarak çağrılmaz. Bu yüzden Script Engine'de sorun olmamalı. Değerlendirilen betiğin kendisi aynı anda çağrılabilir, ancak paylaşılan herhangi bir kaynağa başvurmaz. Neden bunun sorun olduğunu düşünüyorsun? – Gregor

+0

Bu, Stackoverflow'un kardeş sitesi olan programmers.stackexchange.com için daha iyi bir soru olabilir. Kısaca bahsedeceğim: kesinlikle doGet() 'de paylaşılan bir kaynak var, bu' script' değişkenidir. Init() işlevi ile ilgili olarak, init() ve 'doGet()' arasında herhangi bir senkronizasyon olduğunu belirten herhangi bir JEE belgesine işaret edebilir misiniz? Bu temel konular, eğer bu sorunları göremiyorsanız, çoklu okuma hakkında daha fazla bilgi edinmeniz gerekiyor. – markspace

+1

Yazdığım gibi: komut dosyası aynı anda çağrılır. Paylaşıldı. Ancak paylaşılan değişkenler mutlaka iş parçacığı güvenli değildir. komut dosyası kendisi, iş parçacığı başına sunucu isteği olduğundan herhangi bir paylaşılan kaynağa yazma yapmaz. Yani ihtiyacım olan şey, bir js-betiğini çağırmakla ilgili soruya bir cevaptır. Nashorn belgeleri bu konuda sessizdir. Init yöntemi ile ilgili olarak, yukarıdaki geliştirilmiş örneğimde boş olduğunu görebilirsiniz. – Gregor

İlgili konular