您好我有一个Java应用程序,它需要执行输入数量的操作,并为每个操作运行不同的线程:
//create operations to execute
Thread t[] = new Thread [n_operations];
//we create a Bank with N accounts
Bank mybank = new Bank(N);
//execute a separate thread per operation
for (int i = 0; i < n_operations; i++) {
int id = i;
Operation o = new Operation(mybank, id);
t[i]= new Thread (o);
t[i].start();
}
for (int i=0;i<N;i++){
try{
t[i].join();
}catch(Exception e){;}
}
现在我需要在帐户上执行并发传输,其中Bank类的定义如下:
public class Bank {
private static Account[] accounts;
final int MAX_balance = 100000;
int MAX_accounts = 0;
/* Create accounts of a bank */
public Bank (int N) {
accounts = new Account[N];
MAX_accounts = N;
for (int i = 0; i < N; i++)
accounts[i] = new Account (i, 1000);
}
public int getN(){
return MAX_accounts;
}
public synchronized int transfer(int from, int to, int amount) {
synchronized (accounts[from]){
synchronized (accounts[to]){
if (accounts[from].balance () < amount) {
try{
System.out.println("Error during transfer: Not enough Money");
}
catch(Exception err){
return 1;
}
}
accounts[from].sub(amount);
accounts[to].add(amount);
}
}
return 0;
}
}
当程序执行操作时:
public class Operation implements Runnable {
private Bank b;
int id;
Random r;
private final int MAX_TRANSFERENCIAS = 1000;
public Operation (Bank b, int id) {
this.b = b;
this.id = id;
}
public int syncronize(){
return 1;
}
public void run () {
r = new Random();
if(b == null)
throw new RuntimeException("b is null!");
if(r == null)
throw new RuntimeException("r is null!");
int max = b.getN();
//depend if there is a conflict or not
b.transfer (id,r.nextInt(max),r.nextInt(100));
}
}
我收到一系列错误,例如:
at Bank.transfer(Bank.java:28) /* which is "synchronized (accounts[from]){" */
at Operation.run(Operation.java:33) /* which is "b.transfer
(id,r.nextInt(max),r.nextInt(100));" */
at java.lang.Thread.run(Unknown Source)
java.lang.ArrayIndexOutOfBoundsException: 4714
您认为同步还可以吗?
有什么建议吗?非常感谢
更新(我无法回答自己)
主循环中存在概念错误(对于i..to n_operations), 函数传递“int id = i;”作为source_account的参数,而n_operation数大于数组的最大值,因此编译器合理地说:ArrayIndexOutOfBoundsException。
作为最后的贡献,我会请你仔细检查同步是否正确完成,因为我不是多线程的专家。再次感谢,并抱歉今天早上严厉提出问题......
答案 0 :(得分:3)
修改强>
现在我们知道以下行是NPE的来源:
b.transfer (id,r.nextInt(max),r.nextInt(100));
所以最有可能b
或r
是null
。你应该在那里放一个断点并调试它以查看它们是否存在。您还可以使用assert
或日志记录来显示值。另请注意,id
或max
也可能会导致NPE,如果Integer
是null
并且被自动装箱。
这不会导致您的NPE,但要小心n_operations
可能不是== 100?您正在开始n_operations
个帖子,但加入其中的100个:
for (int i=0;i<100;i++){
try {
t[i].join();
} catch(Exception e){;}
}
在这些情况下,我总是使用数组的长度,因此您在分配的内容之间没有不匹配的地方:
for (int i = 0; i < t.length; i++) {
此外,至少应始终记录或打印您的例外情况。捕获和删除异常通常意味着您隐藏了重要的调试信息。
} catch(Exception e){ e.printStackTrace(); }
答案 1 :(得分:1)
您在run()
中使用的变量之一是null,但是哪一个?尝试将以下内容添加到Operation.run()
的开头:
if(b == null)
throw new RuntimeException("b is null!");
if(r == null)
throw new RuntimeException("r is null!");
我认为您从run()
显示的行包含第27行。如果没有,请发布run()
的完整源代码。