2016-08-16 54 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並且在soapui中結束線程數爲2 .. – jagan

回答

0

您發佈的代碼似乎並不很正確,語法 - 你的意思是這樣:

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

假設這是你的意思,那麼就好像多線程使用ExampleProvider的相同實例。這可以解釋爲什麼製作outputResponse本地到execute(然後你可能也想把它傳遞給populateOutputResponse)來修復你的測試。

如果多個線程正在使用ExampleProvider的同一個實例,那麼,因爲您的代碼現在,outputResponse也在這些線程之間共享,並且沒有正在執行同步來防止競爭條件。所以,這樣的事情可能會發生:

  • 線程1個完成setSomeOtherValue(...)outputResponse
  • JVM方面的共享實例切換到線程2和的outputResponse相同的情況下完成setSomeValue(...)outputResponse現在包含線程1和線程2中的狀態
  • JVM上下文切換回線程1,然後基於此混合狀態對象創建OutputResponseEntity

如果您outputResponse本地的execute方法,只是通過它周圍,它實際上就變成線程本地內存,所以你必須每個線程對象的一個​​單獨的實例。這可能是你想要的;如果您不需要在線程之間共享信息,只需將其作爲本地變量。如果你真的需要在線程之間協調sets/gets(在這個簡單的例子中似乎不是這種情況),那麼你需要做一些同步和/或更好地設計程序流(取決於您的需求)。

0

該類不是線程安全的設計。但它顯然被用作某個框架中的組件。不可能,這個框架可以確保線程之間不共享ExampleProvider的實例。如果是這樣的話,那麼你的班級的線程安全就不是問題,並且不會影響你的測試結果。

+0

使用Spring框架,根據我的理解,默認情況下它將它們創建爲單例,因此ExampleProvider在線程之間共享 – jagan