【问题标题】:Can multiple Threads enter into InsertDAO?多个线程可以进入InsertDAO吗?
【发布时间】:2014-02-28 05:43:45
【问题描述】:

我有一个调用 MyService 类的执行方法的客户端类。该方法将依次调用一个 InsertDAO 类。这个 InsertDAO 具有带有实例变量的状态。这仅从 MyService 类的执行方法调用。不能直接调用 InsertDAO 类。

我没有创建任何线程,但我的应用服务器可能会在客户端类上创建线程。现在,我想了解这将如何影响 InsertDAO 类。

  1. 多个线程可以同时访问一个InsertDAO的对象吗? -- 是/否
  2. 当在 Client 类上产生线程时,MyService 类的相同实例将提供给 Client 上的所有线程。然后每个线程都应该调用 MyService 的“执行”方法。这意味着每个线程都有自己的 InsertDAO 实例(我在 MyService 类的执行方法中创建 InsertDAO 对象)。如果是这样,多个线程不能同时进入 InsertDAO。我的理解正确吗?
  3. 如何让多个线程进入 MyService.execute() -- 一些解释,如果这是真的。
  4. 如何让多个线程进入 InsertDAO 类? -- 一些解释,如果这是真的。
  5. 如何在不影响性能的情况下使其成为线程安全的?

专家,请分享您对此的看法。下面是我的代码。

//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
    }
}

【问题讨论】:

  • 编辑引用对象

标签: java multithreading performance


【解决方案1】:

你没有问对问题,线程不进入类,它们进入对象;我们需要查看对象的生命周期以及创建线程的时间。

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

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

this.lineItemsList

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

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

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

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

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

【讨论】:

  • 太棒了。您打消了我对多个线程是否可以一次访问 InsertDAO 对象的怀疑。对可以从外部进行多线程的连接池的引用是一个不错的观点,但对我来说并没有什么影响。因此,如果我们创建一个“门”( MyService.execute() )并且它只有成员变量,并且每个(如 InsertDAO)非静态有状态对象都受到多个线程的保护。很高兴知道。干杯。谢谢你的解释
猜你喜欢
  • 2018-07-17
  • 1970-01-01
  • 1970-01-01
  • 2013-03-08
  • 2018-08-30
  • 2013-09-15
  • 2011-09-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多