2016-03-15 4 views
2

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

Вот мой Java скрипт, который будет оцениваться 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; 
} 

Test Results1 - обратите внимание, что некоторые данные повторяются

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 

Но если добавить "параллельно = истина" в @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 и разрешить его использовать в многопоточном приложении. Как вы видите, я использую переменные глобального скрипта, но они не будут изменены во время его выполнения. Поскольку наш дизайн вращается вокруг веб-службы, которая называет этот сценарий внутренне.

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

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

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

Благодаря

+0

Nashorn является [не поточно-] (https://blogs.oracle.com/nashorn/entry/ nashorn_multi_threading_and_mt). Это то, что вы просите? –

+1

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

ответ

4

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

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

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

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

@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 */ 
} 

Источники:

+0

Привет Спасибо за ответ, это работает для меня. Однако, только один последующий вопрос. Что делает этот «этот» параметр в «scriptObjectMirror.call (это, параметры)» –

+0

@JefreyValencia, хороший вопрос. После дальнейшего исследования похоже, что он становится 'thiz' в' func.apply (thiz, args) 'в JavaScript (см. [Function.prototype.apply() - JavaScript | MDN] (https://developer.mozilla.org/EN-US/Docs/Web/JavaScript/Справочник/Global_Objects/Функция/применить)). Я обновил образец кода, чтобы вместо него использовать «null». Благодаря! – mfulton26

+0

@ mfulton26, Еще раз спасибо –