我有一个调用 MyService 类的执行方法的 Client 类。该方法将依次调用 InsertDAO 类。此 InsertDAO 具有实例变量的状态。这仅从 MyService 类的执行方法调用。不能直接调用InsertDAO类。
我没有创建任何线程,但我的应用程序服务器可能会在客户端类上创建线程。现在,我想了解这将如何影响 InsertDAO 类。
- 多个线程可以同时访问InsertDAO的对象吗? -- 是/否
- 当在 Client 类上生成线程时,将为 Client 上的所有线程提供相同的 MyService 类实例。然后每个线程都应该调用MyService的“execute”方法。这意味着每个线程都有自己的 InsertDAO 实例(我在 MyService 类的执行方法中创建 InsertDAO 对象)。如果是这样,多个线程不能同时进入InsertDAO。我的理解正确吗?
- 多个线程如何可能进入 MyService.execute() - 如果这是真的,一些解释。
- 多个线程如何进入InsertDAO类? -- 一些解释,如果这是真的。
- 如何使其线程安全而不影响性能?
请专家们谈谈对此的看法。下面是我的代码。
//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
}
}
最佳答案
你问的问题不太正确,线程不进入类,它们进入对象;我们需要查看对象的生命周期以及线程何时创建。
现在我不了解您的执行环境 - 我不清楚在哪里创建线程,但我假设以某种方式创建了客户端对象,并且每个对象的performExecution()方法可能在其自己的线程上运行。现在的问题是是否可以同时从两个线程访问任何一个 InsertDAO 对象,或者两个 InsertDAO 对象是否可能共享某些数据,因此两个线程可能会发生干扰。
现在首先我们注意到每个 InsertDAO 对象都是独立的,它们有变量,但这些变量不是静态的。例如,你有
this.lineItemsList
因此,数据由单个对象实例拥有,其他对象(可能在另一个线程中)无法看到附加到this的数据。请注意,如果您有静态数据,则所有实例都可以看到它,并且您会遇到问题。第一条规则:没有静态数据,除非您通过同步访问来保护它。
您遇到潜在问题的一个地方是您请求连接。现在连接通常是池化的,我们真的不想为每个请求打开一个连接,而是从池中获取一个连接,并在使用后返回。整个想法是线程共享同一个池。所以这里的一般原则是,你的InsertDAO对象使用的任何它们没有作为成员变量的东西都必须是线程安全,也就是说,作者必须在多线程访问的预期中编写它它。共享池:作者必须使用某种同步访问。规则 2:看看您使用的内容以及您自己的代码。
最后一点,两个线程可以共享一个 InsertDAO 对象吗?要回答这个问题,请看看您如何创建它们:
public InvoiceVO execute(InvoiceVO createInvoiceVO){
InsertDAO insertDAO = new InsertDAO();
insertDAO.process(createInvoiceVO);
}
在这里你创建了对象,调用它的方法并返回(隐式释放对象),没有其他线程可以看到它,它在你的堆栈上是本地的。因此我们知道只有一个线程使用一个 InsertDAO 对象。规则三:调用者决定有多少线程可以看到一个对象。在您的情况下,您已经确保了一个线程。
关于java - 多个线程可以进入InsertDAO吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22087212/