我对java中的多线程处理很新,现在我必须使用一些遗留类来实现多线程模块。我认为有一些竞争条件的问题,因为我在单线程和多线程执行之间得到了不同的结果。我的主要疑虑如下:
public class Worker implements Runnable{
final private int minIndex; // first index, inclusive
final private int maxIndex; // last index, exclusive
final private MyDTO dto;
private MyService myService;
public Worker(MyDTO dto) {
this.minIndex = dto.getMinIndex();
this.maxIndex = dto.getMaxIndex();
this.dto = dto;
myService = new MyService();
}
public void run() {
int countReg = 0;
if(!initErrors){
try {
Connection conn = ConnectionFactory.getConnection();
for(int i = minIndex ; i<maxIndex; i++){
myService.executeCalculation(dto,conn);
countReg++;
}
conn.close();
} catch (SQLException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
}
public class MyService{
//It has some method to get object from the database
public void executeCalculation(MyDTO dto,Connection conn) {
//I do some actions and
RegolaDAO regolaDAO = new RegolaDAO(conn);
MyObject obj = new MyObject(conn);
// I use obj durin the calculation
}
}
}
public class MyObject{
Connection conn;
public MyObject (Connection conn){
super();
this.conn = conn;
}
}
我的服务是一个无状态对象,然后在MyObject是一个有状态的对象时不会出现任何问题,这可能会产生问题。我和我之后的主要疑问是为每个计算使用new关键字 MyObject obj = new MyObject(); 这有助于我防止竞争条件。
MyObject线程安全吗? 你能给我一些关于我实施的建议吗?
答案 0 :(得分:1)
由于myService
未被更改,因此您可以将其设为最终版。
看来您的dto
在线程之间共享,我会检查它是否也是只读的。
另外conn
如何传递给executeCalculation
,你应该确保你没有使用字段。
答案 1 :(得分:0)
MyObject线程安全吗?你能给我一些关于我实施的建议吗?
由于MyObject
具有非最终字段(myService
),因此它被认为不是线程安全的。如果两个线程使用相同的MyObject
实例,则可以在正确初始化之前使用myService
。正如@Peter指出的那样,将myService
设为final
可以解决该特定问题。
查看代码,以下行调用其他类,因此是线程安全问题的候选者:
if (!initErrors) {
我不知道如何定义initErrors
。如果在线程之间共享,则需要volatile
或AtomicBooolean
。
Connection conn = ConnectionFactory.getConnection();
ConnectionFactory
线程安全吗?多个线程可以一次调用吗?
myService.executeCalculation(dto, conn);
executeCalculation(...)
方法的相同问题。此外,正如@Peter指出的那样,服务正在使用dto
。如果服务正在对dto
实例进行更改,则需要进行同步。