多个线程可以进入InsertDAO吗?

时间:2014-02-28 05:43:46

标签: java multithreading performance

我有一个调用MyService类的execute方法的Client类。此方法将依次调用InsertDAO类。此InsertDAO具有实例变量的状态。这只是从MyService类的execute方法调用。一个人不能直接调用InsertDAO类。

我没有创建任何线程,但我的App Server可能会在Client类上创建线程。现在,我想了解这将如何影响InsertDAO类。

  1. 多个线程可以同时访问InsertDAO的对象吗? - 是/否
  2. 在Client类上生成线程时,会向Client上的所有线程提供相同的MyService类实例。然后每个线程都应该调用MyService的“execute”方法。这意味着每个线程都有自己的InsertDAO实例(我在MyService类的execute方法中创建了InsertDAO对象)。如果是这样,多个线程无法同时进入InsertDAO。我的理解是否正确?
  3. 多个线程如何进入MyService.execute() - 如果这是真的,可以解释一些。
  4. 多个线程如何进入InsertDAO类? - 一些解释,如果这是真的。
  5. 如何在不影响性能的情况下使其保持线程安全?
  6. 专家,请分享您对此的看法。以下是我的代码。

    //code starts here
    public class Client{
        public void performExecution(){
            InvoiceVO createInvoiceVO = new InvoiceVO();
            MyService service = new 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
        }
    }
    

1 个答案:

答案 0 :(得分:2)

你不是在问正确的问题,线程不输入类,它们输入对象;我们需要查看对象的生命周期以及何时创建线程。

现在我不明白你的执行环境 - 我不清楚创建线程的位置,但我会假设创建了客户端对象,并且每个对象的performExecution()方法可以在自己的线程上运行。现在的问题是,是否可以同时从两个线程访问任何一个InsertDAO对象,或者两个InsertDAO对象是否可能共享某些数据,因此两个线程可能会发生干扰。

现在我们首先注意到每个InsertDAO对象是独立的,它们有变量,但这些变量不是静态的。你有例如

this.lineItemsList

因此,数据由单个对象实例拥有,没有其他对象(可能在另一个线程中)可以看到附加到 this 的数据。请注意,如果您有静态数据,则所有实例都可以看到它并且您会遇到问题。第一条规则:NO STATIC DATA,除非您通过同步访问保护它。

您有潜在问题的地方是您要求连接。现在连接通常是池化的,我们真的不希望为每个请求打开一个连接,而是从池中获取一个连接并在我们使用它时返回。整个想法是线程共享同一个池。所以这里的一般原则是你的InsertDAO对象使用的任何东西都没有作为成员变量必须是线程安全,这是作者必须在多线程访问的期望中编写它它。共享池:作者必须使用某种类型的同步访问。规则2:查看您使用的内容以及您自己的代码。

最后一点,两个线程可以共享一个InsertDAO对象吗?要回答一下你如何创建它们:

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

在这里你创建对象,调用它的方法并返回(隐式释放对象),没有其他线程可以看到它,它在你的堆栈上是本地的。因此我们知道只有一个线程使用一个InsertDAO对象。规则三:调用者确定有多少线程可以看到一个对象。在你的情况下,你确保了一个线程。