线程中的异常"线程-2"我的代码中的java.lang.NullPointerException.error

时间:2014-04-28 17:30:34

标签: java arrays multithreading locking

我的代码工作(至少在某种程度上),我必须改变一些东西,因为现在它甚至都不会启动。代码中没有显示错误,但是当我尝试运行它时会出现这样的错误:

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");



        }
    }

有什么建议吗?

2 个答案:

答案 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,而所有其他线程都在等待。