2014-02-28 17 views
2

我有一個Client類調用MyService類的execute方法。該方法將依次調用一個InsertDAO類。這個InsertDAO具有實例變量的狀態。這是僅從MyService類的execute方法調用的。不能直接調用InsertDAO類。多個線程可以輸入到InsertDAO嗎?

我沒有創建任何線程,但我的App Server可能會在客戶端類上創建線程。現在,我想了解這將如何影響InsertDAO類。

  1. 多個線程可以同時訪問InsertDAO的對象嗎? - 是/否
  2. 當在客戶端類上生成線程時,MyService類的同一實例將被賦予給客戶端上的所有線程。然後每個線程都應該調用MyService的「execute」方法。這意味着每個線程都有自己的InsertDAO實例(我在MyService類的execute方法內部創建了InsertDAO對象)。如果是這樣,多個線程不能同時進入到InsertDAO。我的理解是否正確?
  3. 怎麼可能多個線程進入MyService.execute() - 一些解釋,如果這是真的。
  4. 多線程如何進入InsertDAO類? - 一些解釋,如果這是真的。
  5. 如何在不影響性能的情況下使線程安全?

專家,請分享您對此的看法。以下是我的代碼。

//code starts here 
public class Client{ 
    public void performExecution(){ 
     InvoiceVO createInvoiceVO = new InvoiceVO(); 
     MyService service = mew MyService(); 
      createInvoiceVO = service.execute(createInvoiceVO); 
     //retrieve successful/failure information from createInvoiceVO 
    } 
} 

public class MyService{ 
    public InvoiceVO execute(InvoiceVO createInvoiceVO){ 
     InsertDAO insertDAO = new InsertDAO(); 
      insertDAO.process(createInvoiceVO); 
    } 
} 

public class InsertDAO{ 
    private List<LineItem> lineItemsList = new ArrayList<LineItem>(); 
    private List<TaxVO> taxVOList = new ArrayList<TaxVO>(); 
    private Connection connection = null; 

    public InvoiceVO process(InvoiceVO createInvoiceVO){ 
     this.lineItemsList = createInvoiceVO.getLineItemsList(); 
     this.taxVOList = createInvoiceVO.getTaxVOList(); 

     connection = getConnection(); 
     //insert tax vo objects 
     insertTaxVOObjects(taxVOList); 

     //insert line items 
     insertLineItems(this.lineItemsList); 

     //commit operation 

     //close connection 
     closeConnection(); 
    } 

    private void insertTaxVOObjects(List<TaxVO> taxVOList){ 
     //code to insert TaxVO objects 
    } 

    private void insertLineItems(List<LineItem> lineItemsList){ 
     //code to insert LineItem objects 
    } 

    private void getConnection(){ 
     //code to return connection 
    } 

    private void closeConnection(){ 
     //code to close connection 
    } 
} 
+0

編輯參考對象 – Gana

回答

2

你不是在問正確的問題,線程不輸入類,它們輸入對象;我們需要查看對象的生命週期以及何時創建線程。

現在我不明白你的執行環境 - 我不清楚線程是在哪裏創建的,但我會假設客戶端對象被創建並且每個對象的performExecution()方法可以在它自己的線程上運行。現在的問題是,是否可以同時從兩個線程訪問任何一個InsertDAO對象,或者兩個InsertDAO對象是否可能共享某些數據,因此可能會影響兩個線程。

現在首先我們注意到每個InsertDAO對象是分開的,它們都有變量,但這些變量不是靜態的。您有例如

this.lineItemsList 

這樣的數據是由一個單一的對象實例所擁有的,沒有其他物體(可能在另一個線程),可以看到連接到這個數據。請注意,如果您有static數據所有實例都可以看到它,並且您將遇到問題。第一條規則:沒有靜態數據,除非你用同步訪問保護它。

你有一個潛在問題的地方是你要求連接。現在連接通常會被合併,我們實際上不希望爲每個請求打開一個連接,而是從一個池中獲得一個連接,並在我們使用它時返回。整個想法是線程共享相同的池。所以這裏的一般原則是,任何你的InsertDAO對象使用它們沒有作爲成員變量必須是線程安全的,這是作者必須寫它在期望多線程訪問它。共享池:作者必須使用某種類型的同步訪問。規則2:看看你使用的是什麼以及你自己的代碼。

最後一位,兩個線程可以共享一個InsertDAO對象嗎?爲了回答這個問題看你如何創建它們:

public InvoiceVO execute(InvoiceVO createInvoiceVO){ 
    InsertDAO insertDAO = new InsertDAO(); 
     insertDAO.process(createInvoiceVO); 
} 

在這裏,您創建對象,調用它的方法和返回(隱式釋放的對象),沒有其他線程可以看到這一點,這是你的堆棧中的局部。因此我們知道只有一個線程使用一個InsertDAO對象。規則三:調用者確定有多少線程可以看到一個對象。在你的情況下,你已經確保了一個線程。

+0

太好了。您已經擺脫了我對多線程是否一次可以訪問InsertDAO對象的懷疑。提到可以從外部進行多線程的連接池,這是一個很好的觀點,並沒有引起我的興趣。因此,如果我們創建一個「門」(MyService.execute()),並且如果它只有成員變量,並且每個(如InsertDAO)非靜態有狀態對象都受到多線程保護。這很好理解。乾杯。感謝您的解釋 – Gana

+0

很好的解釋。 – Rembo

相關問題