2015-12-08 2 views
2

Ниже я поделился своим кодом, в котором я пытаюсь использовать потокобезопасный Nashorn как механизм сценариев для оценки простой математической формулы. Формула будет похожа на «a * b/2», где & b будет поднят с объекта карты.Nashorn in thread safe способ

public class EvaluateFormulas { 

@Autowired 
NashornThreadPool pool; 

private ScriptEngineManager factory; 
private ScriptEngine engine; 
private ScriptContext context; 

@PostConstruct 
public void setup() { 
    factory = new ScriptEngineManager(); 
    engine = factory.getEngineByName("nashorn"); 
    context = engine.getContext(); 
} 

public void evaluate() { 
    pool.getThreadPoolExecutor().submit(new Runnable() { 
     @Override 
     public void run() { 
      Double result; 
      Bindings bind = engine.createBindings(); 
      bind.putAll(map); 
      context.setBindings(bind, ScriptContext.GLOBAL_SCOPE); 
      try { 
       result = (Double) engine.eval(formula); 
      } catch (ScriptException e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
      } 
     } 
    }); 
} 
} 

Мне нужно знать, поможет ли этот подход сделать поток Nashorn безопасным для этого прецедента. Я прочитал в Attila's answer, что мы можем совместно использовать объекты движка сценариев между потоками, так как они являются потокобезопасными.

Для привязок и Eval, так как мы создаем новый поток для каждого исполнения оценки и каждый поток имеет свою собственную ссылку на объект для объекта привязки. Итак, полностью ли эта реализация будет потокобезопасной?

ответ

1

Я не думаю, что это будет потокобезопасным, поскольку вы меняете привязки, в то время как другой поток потенциально может выполнять код. На самом деле вам не нужно это делать; вы можете просто создать совершенно новый контекст, а затем оценить сценарий в этом контексте. Я бы сделал что-то вроде этого:

public void evaluate() { 
    pool.getThreadPoolExecutor().submit(new Runnable() { 
     @Override 
     public void run() { 
      Double result; 

      ScriptContext myContext = new SimpleScriptContext(); 
      Bindings bindings = engine.createBindings(); 
      bindings.putAll(map); 
      myContext.setBindings(bindings, ScriptContext.ENGINE_SCOPE); 

      try { 
       result = (Double) engine.eval(formula, myContext); 
      } catch (ScriptException e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
      } 
     } 
    }); 
} 

Теперь каждый скрипт оценивается в своем собственном контексте.

+0

Я использую отдельный объект привязки для каждого выполнения, например 'SimpleBindings simpleBindings = new SimpleBindings();' и затем 'engine.eval (script, simpleBindings);'. Я полностью пропустил контекст. Безопасна ли эта нить? – faizan

+0

Я не совсем уверен, но я предполагаю не потому, что он будет использовать тот же контекст. –

 Смежные вопросы

  • Нет связанных вопросов^_^