Nashorn MultiThread Программирование

Можете ли вы помочь мне, если следующий код будет работать в многопоточном приложении.

Вот мой Java Script, который будет оценен 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 + ", referenceNumber: " + referenceNumber + ", validateNumber: " + validateNumber + ", sum: " + sum + ", checkDigit: " + checkDigit + ", statusCode" + statusCode);

    return statusCode;
}

Вот как я создаю свой скрипт-движок

ScriptEngine engine = new ScriptEngineManager().getEngineByName("nashorn");
engine.eval(myScript);

При тестировании с использованием Testng это работает без ошибок

@Test(dataProvider = "validReferenceNumbers", timeOut = 3000)
public final void testValidReferenceNumber(String referenceNumber) throws NoSuchMethodException, ScriptException {
    Map<String, String> parameters = new HashMap<>();
    parameters.put("referenceNumber", referenceNumber);   
    Invocable invocable = (Invocable) engine;
    Object result = invocable.invokeFunction("validate", parameters);       
    Assert.assertEquals(statusCode, "000");
}

@DataProvider(name = "validReferenceNumbers")
private Iterator<Object[]> validReferenceNumbers() throws FileNotFoundException {
    Iterator<Object[]> testData = null;  
    // please assume that will be initilized correctly 
    return testData;
}

Результаты теста1 - обратите внимание, что некоторые данные повторяются

Thread: 10, isValid: true, referenceNumber: 18058888, validateNumber: 1805888, sum: 38, checkDigit: 8, statusCode0000
Thread: 11, isValid: true, referenceNumber: 18058888, validateNumber: 1805888, sum: 38, checkDigit: 8, statusCode0000
Thread: 12, isValid: true, referenceNumber: 17028884, validateNumber: 1702888, sum: 34, checkDigit: 4, statusCode0000
Thread: 13, isValid: true, referenceNumber: 18028885, validateNumber: 1802888, sum: 35, checkDigit: 5, statusCode0000
Thread: 14, isValid: true, referenceNumber: 18058888, validateNumber: 1805888, sum: 38, checkDigit: 8, statusCode0000
Thread: 15, isValid: true, referenceNumber: 17098881, validateNumber: 1709888, sum: 41, checkDigit: 1, statusCode0000
Thread: 16, isValid: true, referenceNumber: 17098881, validateNumber: 1709888, sum: 41, checkDigit: 1, statusCode0000
Thread: 17, isValid: true, referenceNumber: 18028885, validateNumber: 1802888, sum: 35, checkDigit: 5, statusCode0000
Thread: 18, isValid: true, referenceNumber: 18058888, validateNumber: 1805888, sum: 38, checkDigit: 8, statusCode0000
Thread: 19, isValid: true, referenceNumber: 17058887, validateNumber: 1705888, sum: 37, checkDigit: 7, statusCode0000
Thread: 20, isValid: true, referenceNumber: 18058888, validateNumber: 1805888, sum: 38, checkDigit: 8, statusCode0000
Thread: 21, isValid: true, referenceNumber: 18058888, validateNumber: 1805888, sum: 38, checkDigit: 8, statusCode0000
Thread: 22, isValid: true, referenceNumber: 18058888, validateNumber: 1805888, sum: 38, checkDigit: 8, statusCode0000
Thread: 23, isValid: true, referenceNumber: 18058888, validateNumber: 1805888, sum: 38, checkDigit: 8, statusCode0000
Thread: 24, isValid: true, referenceNumber: 18058888, validateNumber: 1805888, sum: 38, checkDigit: 8, statusCode0000
Thread: 25, isValid: true, referenceNumber: 18028885, validateNumber: 1802888, sum: 35, checkDigit: 5, statusCode0000
Thread: 26, isValid: true, referenceNumber: 18058888, validateNumber: 1805888, sum: 38, checkDigit: 8, statusCode0000
Thread: 27, isValid: true, referenceNumber: 18028885, validateNumber: 1802888, sum: 35, checkDigit: 5, statusCode0000
Thread: 28, isValid: true, referenceNumber: 18028885, validateNumber: 1802888, sum: 35, checkDigit: 5, statusCode0000
Thread: 29, isValid: true, referenceNumber: 18028885, validateNumber: 1802888, sum: 35, checkDigit: 5, statusCode0000
Thread: 30, isValid: true, referenceNumber: 18028885, validateNumber: 1802888, sum: 35, checkDigit: 5, statusCode0000
Thread: 31, isValid: true, referenceNumber: 18028885, validateNumber: 1802888, sum: 35, checkDigit: 5, statusCode0000
Thread: 32, isValid: true, referenceNumber: 18028885, validateNumber: 1802888, sum: 35, checkDigit: 5, statusCode0000
Thread: 33, isValid: true, referenceNumber: 17058887, validateNumber: 1705888, sum: 37, checkDigit: 7, statusCode0000
Thread: 34, isValid: true, referenceNumber: 18028885, validateNumber: 1802888, sum: 35, checkDigit: 5, statusCode0000
Thread: 35, isValid: true, referenceNumber: 18058888, validateNumber: 1805888, sum: 38, checkDigit: 8, statusCode0000
Thread: 36, isValid: true, referenceNumber: 18058888, validateNumber: 1805888, sum: 38, checkDigit: 8, statusCode0000
Thread: 37, isValid: true, referenceNumber: 18058888, validateNumber: 1805888, sum: 38, checkDigit: 8, statusCode0000
Thread: 38, isValid: true, referenceNumber: 18058888, validateNumber: 1805888, sum: 38, checkDigit: 8, statusCode0000
Thread: 39, isValid: true, referenceNumber: 18058888, validateNumber: 1805888, sum: 38, checkDigit: 8, statusCode0000
Thread: 40, isValid: true, referenceNumber: 18058888, validateNumber: 1805888, sum: 38, checkDigit: 8, statusCode0000
Thread: 41, isValid: true, referenceNumber: 18058888, validateNumber: 1805888, sum: 38, checkDigit: 8, statusCode0000
Thread: 42, isValid: true, referenceNumber: 18058888, validateNumber: 1805888, sum: 38, checkDigit: 8, statusCode0000
Thread: 43, isValid: true, referenceNumber: 18028885, validateNumber: 1802888, sum: 35, checkDigit: 5, statusCode0000
Thread: 44, isValid: true, referenceNumber: 18058888, validateNumber: 1805888, sum: 38, checkDigit: 8, statusCode0000
Thread: 45, isValid: true, referenceNumber: 18058888, validateNumber: 1805888, sum: 38, checkDigit: 8, statusCode0000
Thread: 46, isValid: true, referenceNumber: 07034880, validateNumber: 0703488, sum: 30, checkDigit: 0, statusCode0000
Thread: 47, isValid: true, referenceNumber: 07034880, validateNumber: 0703488, sum: 30, checkDigit: 0, statusCode0000
Thread: 48, isValid: true, referenceNumber: 07009882, validateNumber: 0700988, sum: 32, checkDigit: 2, statusCode0000

Но если я добавлю "Parallel= True" в @DataProvider, мои сценарии начинают терпеть неудачу

@Test(dataProvider = "validReferenceNumbers", timeOut = 3000)
public final void testValidReferenceNumber(String referenceNumber) throws NoSuchMethodException, ScriptException {
    Map<String, String> parameters = new HashMap<>();
    parameters.put("referenceNumber", referenceNumber);   
    Invocable invocable = (Invocable) engine;
    Object result = invocable.invokeFunction("validate", parameters);       
    Assert.assertEquals(statusCode, "000");
}

@DataProvider(name = "validReferenceNumbers", parallel=true)
private Iterator<Object[]> validReferenceNumbers() throws FileNotFoundException {
    Iterator<Object[]> testData = null;  
    // please assume that will be initilized correctly 
    return testData;
}

Результаты теста2 - обратите внимание, что некоторые данные повторяются, чтобы показать, что один и тот же ссылочный номер может случайно произойти во время теста

Thread: 29, isValid: true, referenceNumber: 18058888, validateNumber: 1805888, sum: 38, checkDigit: 8, statusCode0000
Thread: 22, isValid: false, referenceNumber: 18058888, validateNumber: 1805888, sum: 1, checkDigit: 1, statusCode0001
Thread: 25, isValid: false, referenceNumber: 18058888, validateNumber: 1805888, sum: 1, checkDigit: 1, statusCode0001
Thread: 21, isValid: true, referenceNumber: 17098881, validateNumber: 1709888, sum: 41, checkDigit: 1, statusCode0000
Thread: 27, isValid: false, referenceNumber: 18028885, validateNumber: 1802888, sum: 1, checkDigit: 1, statusCode0001
Thread: 20, isValid: true, referenceNumber: 17098881, validateNumber: 1709888, sum: 41, checkDigit: 1, statusCode0000
Thread: 26, isValid: true, referenceNumber: 17058887, validateNumber: 1705888, sum: 37, checkDigit: 7, statusCode0000
Thread: 24, isValid: true, referenceNumber: 17028884, validateNumber: 1702888, sum: 34, checkDigit: 4, statusCode0000
Thread: 23, isValid: false, referenceNumber: 18028885, validateNumber: 1802888, sum: 1, checkDigit: 1, statusCode0001
Thread: 28, isValid: true, referenceNumber: 18058888, validateNumber: 1805888, sum: 38, checkDigit: 8, statusCode0000
Thread: 30, isValid: true, referenceNumber: 18058888, validateNumber: 1805888, sum: 38, checkDigit: 8, statusCode0000
Thread: 32, isValid: true, referenceNumber: 18028885, validateNumber: 1802888, sum: 35, checkDigit: 5, statusCode0000
Thread: 34, isValid: true, referenceNumber: 18028885, validateNumber: 1802888, sum: 35, checkDigit: 5, statusCode0000
Thread: 31, isValid: true, referenceNumber: 18058888, validateNumber: 1805888, sum: 38, checkDigit: 8, statusCode0000
Thread: 36, isValid: true, referenceNumber: 18028885, validateNumber: 1802888, sum: 35, checkDigit: 5, statusCode0000
Thread: 38, isValid: true, referenceNumber: 18058888, validateNumber: 1805888, sum: 38, checkDigit: 8, statusCode0000
Thread: 40, isValid: true, referenceNumber: 18028885, validateNumber: 1802888, sum: 35, checkDigit: 5, statusCode0000
Thread: 42, isValid: true, referenceNumber: 18028885, validateNumber: 1802888, sum: 35, checkDigit: 5, statusCode0000
Thread: 44, isValid: true, referenceNumber: 18058888, validateNumber: 1805888, sum: 38, checkDigit: 8, statusCode0000
Thread: 33, isValid: true, referenceNumber: 18028885, validateNumber: 1802888, sum: 35, checkDigit: 5, statusCode0000
Thread: 46, isValid: true, referenceNumber: 18058888, validateNumber: 1805888, sum: 38, checkDigit: 8, statusCode0000
Thread: 48, isValid: true, referenceNumber: 18058888, validateNumber: 1805888, sum: 38, checkDigit: 8, statusCode0000
Thread: 35, isValid: false, referenceNumber: 18058888, validateNumber: 1805888, sum: 30, checkDigit: 0, statusCode0001
Thread: 50, isValid: true, referenceNumber: 18058888, validateNumber: 1805888, sum: 38, checkDigit: 8, statusCode0000
Thread: 37, isValid: true, referenceNumber: 18058888, validateNumber: 1805888, sum: 38, checkDigit: 8, statusCode0000
Thread: 39, isValid: true, referenceNumber: 18028885, validateNumber: 1802888, sum: 35, checkDigit: 5, statusCode0000
Thread: 41, isValid: true, referenceNumber: 17058887, validateNumber: 1705888, sum: 37, checkDigit: 7, statusCode0000
Thread: 52, isValid: true, referenceNumber: 18058888, validateNumber: 1805888, sum: 38, checkDigit: 8, statusCode0000
Thread: 54, isValid: true, referenceNumber: 18058888, validateNumber: 1805888, sum: 38, checkDigit: 8, statusCode0000
Thread: 43, isValid: true, referenceNumber: 18028885, validateNumber: 1802888, sum: 35, checkDigit: 5, statusCode0000
Thread: 45, isValid: true, referenceNumber: 18058888, validateNumber: 1805888, sum: 38, checkDigit: 8, statusCode0000
Thread: 56, isValid: true, referenceNumber: 07009882, validateNumber: 0700988, sum: 32, checkDigit: 2, statusCode0000
Thread: 58, isValid: true, referenceNumber: 07034880, validateNumber: 0703488, sum: 30, checkDigit: 0, statusCode0000
Thread: 47, isValid: true, referenceNumber: 18058888, validateNumber: 1805888, sum: 38, checkDigit: 8, statusCode0000
Thread: 49, isValid: true, referenceNumber: 18058888, validateNumber: 1805888, sum: 38, checkDigit: 8, statusCode0000
Thread: 51, isValid: true, referenceNumber: 18058888, validateNumber: 1805888, sum: 38, checkDigit: 8, statusCode0000
Thread: 53, isValid: true, referenceNumber: 18028885, validateNumber: 1802888, sum: 35, checkDigit: 5, statusCode0000
Thread: 55, isValid: true, referenceNumber: 18058888, validateNumber: 1805888, sum: 38, checkDigit: 8, statusCode0000
Thread: 57, isValid: true, referenceNumber: 07034880, validateNumber: 0703488, sum: 30, checkDigit: 0, statusCode0000

Может ли кто-нибудь подтвердить, могу ли я инициализировать ScriptEngine и разрешить его использование в многопоточном приложении. Как видите, я использую глобальные переменные скрипта, но они не будут изменены во время его выполнения. Поскольку наш дизайн вращается вокруг веб-сервиса, который вызывает этот скрипт внутри.

PS В моем понимании @DataProvider(параллельный =true) является правильным способом проверки многопоточности, поэтому, если я ошибаюсь, укажите это.

Редактировать Может кто-нибудь сказать мне, как я могу изменить свой код / ​​скрипт, чтобы я мог инициализировать ScriptEngine и разрешить его использование в многопоточном приложении. Так как я не хочу разбирать файлы скриптов снова и снова.

Как я ранее думал, что если скрипт не использует глобальные переменные для сохранения состояния, все будет в порядке, но, видимо, этого недостаточно.

Спасибо

1 ответ

Решение

Вы можете инициализировать ScriptEngine и использовать его в многопоточном приложении.

Вместо engine.eval(myScript); вы хотите создать CompiledScript экземпляр, который вы можете позже оценить в Bindings экземпляры:

Compilable compilable = (Compilable) engine;
CompiledScript script = compilable.compile(myScript);

И вместо того, чтобы использовать ваш engine как Invocable вам нужно будет создать Bindings экземпляр для каждого потока / теста, оцените скомпилированный скрипт в нем, получите зеркало объекта скрипта, которое оборачивает функцию, и затем вызовите функцию:

@Test(dataProvider = "validReferenceNumbers", timeOut = 3000)
public final void testValidReferenceNumber(String referenceNumber) throws ScriptException {
    Map<String, String> parameters = new HashMap<>();
    parameters.put("referenceNumber", referenceNumber);
    Bindings bindings = engine.createBindings();
    script.eval(bindings);
    ScriptObjectMirror scriptObjectMirror = (ScriptObjectMirror) bindings.get("validate");
    Object result = scriptObjectMirror.call(null, parameters);
    /* insert result assertions here */
}

Источники:

Другие вопросы по тегам