Ответ 1
Итак, я запустил эксперимент, и отчеты двигателей Rhino "Mozilla Rhino" MULTITHREADED, которые JavaDocs утверждает
"MULTITHREADED" - реализация двигателя внутренне поточно-безопасна и скрипты могут выполняться одновременно, хотя эффекты scriptвыполнение в одном потоке может быть видимым для скриптов на других потоках. "
Здесь код... он выглядит небезопасным для меня, пока привязки, которые вы проходите, тоже потокобезопасны.
package org.rekdev;
import java.util.*;
import javax.script.*;
public class JavaScriptWTF {
public static void main( String[] args ) {
ScriptEngineManager mgr = new ScriptEngineManager();
List<ScriptEngineFactory> factories = mgr.getEngineFactories();
for ( ScriptEngineFactory factory : factories ) {
System.out.println( String.format(
"engineName: %s, THREADING: %s",
factory.getEngineName(),
factory.getParameter( "THREADING" ) ) );
}
}
}
... выход...
engineName: AppleScriptEngine, THREADING: null
engineName: Mozilla Rhino, THREADING: MULTITHREADED
Чтобы ответить на ваш точный вопрос...
-
Предполагается, что привязки привязаны к потоку?
Мне кажется, что вы несете ответственность за то, чтобы сделать их потокобезопасными. Другими словами, передавайте только неизменяемые объекты и независимо от того, является ли движок безопасным потоком или не становится проблемой. -
Разрешено ли нескольким потокам совместно использовать один экземпляр ScriptEngine?
Это звучит для меня, как они могут, но ключ - это разделение состояний, которое может произойти через Bindings. Неизменяемые объекты - ваш друг. -
... или должен ли каждый поток построить недолговечный экземпляр?
Мне кажется, что лучший способ подумать об этом заключается в том, что каждое выполнение eval является короткоживущим экземпляром. -
... или сохранить их в пуле?
В этот день и в возрасте, пытаясь объединить ресурсы самостоятельно, редко бывает хорошей идеей. Дайте короткоживущему экземпляру выстрел, измерьте его производительность и отработайте оттуда. -
Что произойдет, если несколько потоков одновременно вызовут ScriptEngine.eval(...)?
Если я правильно понял ответ Reino для Rhino для MULTITHREADING, ScriptEngine.eval должен быть в порядке с одновременными вызовами. -
Тот же вопрос для экземпляров CompiledScript
В JavaDocs говорится, что "Изменения в состоянии ScriptEngine, вызванные выполнением CompiledScript, могут отображаться при последующих запусках скриптов с помощью движка". http://docs.oracle.com/javase/6/docs/api/javax/script/CompiledScript.html. Таким образом, они не звучат в потоковом режиме в среде, где вы пытаетесь свести к минимуму количество экземпляров ScriptEngine. -
Те же вопросы для реализации интерфейса, сгенерированные с помощью Invocable.getInterface(...)? Вы здесь по своему усмотрению. Я не понимаю, почему или когда эта способность будет использоваться, и это звучит для меня, как будто вы можете "прыгать с акулой" здесь. Если вы хотите углубиться в язык сценариев, я рекомендую отказаться от JavaScript и посмотреть Groovy для более скриптовой Java.
-
Предположительно, объекты, помещенные в Bindings, следуют за сборкой мусора Java. Как насчет сбора мусора объектов, которые не попадают в привязки?
Если они не попадают в привязки, я ожидаю, что они будут привязаны к ScriptEngine и следуют его жизненному циклу (на основе документов, которые я прочитал). Объединение экземпляров ScriptEngine не похоже на отличную идею.