我的代码工作(至少在某种程度上),我必须改变一些东西,因为现在它甚至都不会启动。代码中没有显示错误,但是当我尝试运行它时会出现这样的错误:
Exception in thread "Thread-2" java.lang.NullPointerException
at azsystem3.Add.run(Main.java:57)
at java.lang.Thread.run(Thread.java:662)
和(Main.java:57)就是这一行:sum.s+=a[i];
我如何解决它?
这是我的相关代码:
package azsystem3;
import java.util.*;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
class Fill implements Runnable{
int []a;
static Random b = new Random();
int start;
int end;
public Fill(int[]a,int start,int end){
this.a=a;
this.start=start;
this.end=end;
}
public void run(){
for(int i=this.start;i<this.end;i++){
a[i]=b.nextInt(100);
}
}
}
class value{
int s;
}
class Add implements Runnable{
value sum;
Lock L ;
int[]a;
int start;
int end;
//public long sum=0;
public Add(int[]a,int start, int end,Lock L,value s){
this.L=L;
this.start=start;
this.end=end;
sum=s;
}
public void run(){
int i;
for( i=start;i<end;i++)
L.lock();
sum.s+=a[i];
L.unlock();
}
}
class main {
public static void main(String[] args) {
value sum=new value();
Lock Lock=new ReentrantLock();
int[] array = new int[100000];
Scanner sc=new Scanner (System.in);
System.out.println ("Enter number : ");
int n = sc.nextInt();
int tmp = 100000 / n;
Thread[] t = new Thread[n];
for (int i = 0; i < n; i++) {
t[i] = new Thread(new Fill(array, (i) * tmp, (i + 1) * tmp));
t[i].start();
}
for (int i = 0; i < n; i++) {
try {
t[i].join();
} catch (InterruptedException exception) {
}
}
Thread[] t1 = new Thread[n];
Add[] add = new Add[n];
long start = System.currentTimeMillis();
for (int i = 0; i < n; i++) {
add[i] = new Add(array, (i) * tmp, (i + 1) * tmp,Lock,sum);
t1[i] = new Thread(add[i]);
t1[i].start();
}
for (int i = 0; i < n; i++) {
try {
t1[i].join();
} catch (InterruptedException exception) {
}
}
long end = System.currentTimeMillis();
System.out.println("sum : " + sum);
System.out.println("time : " + (end - start) + "ms");
}
}
有什么建议吗?
答案 0 :(得分:1)
线程安全不仅需要锁定代码中的run()
- 方法,还应该让您的私有成员Add
,尤其是sum
成员,最终即可。否则,线程可能会看到value
类型的未完全初始化的对象,其中sum
- 成员仍为null
。
请注意:请尝试遵循标准Java代码约定以提高可读性。
另一个观察,这段代码
for( i=start;i<end;i++) // missing opening bracket {
L.lock();
sum.s+=a[i];
L.unlock(); // missing closing bracket }
相当于:
for( i=start;i<end;i++) {
L.lock();
}
sum.s+=a[i];
L.unlock();
由于托架处理不当而导致锁定,我不相信任何线程安全。
答案 1 :(得分:1)
虽然它看起来像是线程安全问题,但NullPointerException
的原因很简单:
在Add
类的构造函数中,您忘记分配int
数组实例变量a
,即缺少简单的this.a=a;
。
这就是为什么你应该尽可能地将每个实例变量声明为final
的原因。然后编译器将告诉您每个缺失的值赋值。
当然,您必须修复Add.run()
方法中缺少的大括号,否则您将获得死锁。在你的情况下,只有第一个线程抛出NullPointerException
,而所有其他线程都在等待。