2016-08-16 1 views
0

Ниже приведен пример класса (измененный с того, который я тестировал), я хотел бы знать, является ли это потокобезопасным классом.Переменная экземпляра и безопасность потока в java

Я вижу другие сообщения и блоги, на которых ответили, что переменные экземпляра не обязательно являются потокобезопасными. (большинство примеров, показанных с помощью примитивных типов)

Когда я создаю объект OutputResponse вне метода и загружаю его с soapui, он терпел неудачу, но когда я создаю объект внутри метода, тест нагрузки всегда преуспел.

@Service 
public class ExampleProvider { 

    private OutputResponse outputResponse; 

     @Post 
     @Path("/test") 
     @Consumes("application/json") 
    @Produces("application/json") 
     public OutputResponseEntity execute (InputRequest inputRequest) { 

     outputResponse = new OutputResponse(); 
      outputResponse.setSomeValue("this is test"); 
      populateOutputResponse(); 
     } 

     private OutoutResponseEntity<OutputResponse> populateOutputResponse() { 
      if(null != inputRequest) { 
       outputResponse.setSomeOtherValue(inputRequest.getName()); 
      } 
      return new OutputResponseEntity(outputResponse,httpstatus.OK); 
     } 
} 
+0

Какие рамки вы используете для '@ Service' и остальных этих аннотаций? – markspace

+1

Нет, это не потокобезопасно. У вас есть личные данные, которые изменяются. Это определение «небезопасно». Удалите элемент частных данных и сделайте OutputResponse локальным для метода. Это потокобезопасность. – duffymo

+0

@duffymo Я ожидал того же, создав переменную OutputResponse локально внутри метода, является потокобезопасной и сохраняя ее как переменную экземпляра «не потокобезопасной», но тесты нагрузки успешно выполняются в обоих случаях всегда. Протестировано с двумя потоками, начальное количество потоков - 20 и конец потока подсчитывается как 2 в soapui .. – jagan

ответ

0

Опубликованный код, кажется, не совсем правильно, синтаксический - Вы имели в виду что-то вроде:

public OutputResponseEntity execute (InputRequest inputRequest) { 
    outputResponse = new OutputResponse(); 
    outputResponse.setSomeValue("this is test"); 
    return populateOutputResponse(inputRequest); 
} 

Если предположить, что это то, что вы имели в виду, то кажется, что несколько потоков с помощью тот же экземпляр ExampleProvider. Это объясняет, почему сделать outputResponse локальным для execute (и тогда вы, вероятно, захотите передать его также populateOutputResponse), исправляет ваши тесты.

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

  • нить 1 завершает setSomeOtherValue(...) на общем экземпляре outputResponse
  • контексте виртуальной машины Java переключается на поток 2 и завершает setSomeValue(...) на том же экземпляре outputResponse. outputResponse теперь содержит состояние из обоих потоков 1 и 2
  • Контекст JVM переключается обратно в поток 1, который затем создает OutputResponseEntity на основе этого объекта смешанного состояния.

Если вы outputResponse локальной по отношению к методу execute и просто передать его вокруг, он фактически становится поток локальной памяти, так что вы будете иметь отдельный экземпляр этого объекта в потоке. Это, вероятно, то, что вы хотите; если вам не нужно обмениваться информацией между потоками, просто сделайте это локальным var. Если вам действительно нужна координация наборов/между потоками (что не похоже на этот простой пример), вам нужно будет сделать какую-то синхронизацию и/или сконструировать поток программы лучше (в зависимости от твои нужды).

0

Этот класс не является потокобезопасным по дизайну. Но он явно используется как компонент в некоторых рамках. Не исключено, что эта структура гарантирует, что ни один экземпляр вашего ExampleProvider не будет использоваться совместно между потоками. Если это так, то безопасность потоков вашего класса не вызывает беспокойства и не повлияет на результат теста.

+0

Spring framework используется, и по моему пониманию он создает их по умолчанию как singleton, поэтому ExampleProvider получает общий доступ к потокам – jagan