Java产生Ghost线程

时间:2016-09-28 15:10:15

标签: java multithreading exception

我正在研究一种新的NLP分类器算法,并希望使其成为多线程。我的实现执行它应该正确执行的操作,但是当使用threads = 4运行时,我得到了一些奇怪的异常。 这是我的方法:

protected void generateCoordinatesMultiThread(Category generate, int threads){
    WordMap wordMap = new WordMap();
    wordOccurences = new int[semanticspace.getVectorAmount()][generate.getSize()];
    tfidf = new double[semanticspace.getVectorAmount()][generate.getSize()];
    ntfidf = new double[semanticspace.getVectorAmount()][generate.getSize()];
    Thread[] threadGroup = new Thread[threads];
    try{
        System.out.println(generate.getSize()+" objects in "+threads+" threads");
        for(int i=0;i<threads;i++){
            int start=(generate.getSize()/threads)*i;
            int end=((generate.getSize()/threads)*(i+1))-1;
            if(i==threads-1){
                end=generate.getSize();
            }
            System.out.println("Start: "+start+" end: "+end);
            threadGroup[i] = new Thread(new WordMapper(this,start,end,generate,"WordMapper-"+i,wordMap));
            threadGroup[i].start();
        }
        for(int i=0;i<threads;i++){
            threadGroup[i].join();
        }
        System.out.println("First multi-thread step finished");
        wordMap.mapSemanticSpace(semanticspace);
        wordMap.print();
    }catch(Exception e){
        System.out.println(e.getMessage());
    }
    System.out.println("Starting frequency workers");
    threadGroup = new Thread[threads];
    try{
        System.out.println(generate.getSize()+" objects in "+threads+" threads");
        for(int i=0;i<threads;i++){
            int start=(generate.getSize()/threads)*i;
            int end=((generate.getSize()/threads)*(i+1))-1;
            if(i==threads-1){
                end=generate.getSize();
            }
            System.out.println("Start: "+start+" end: "+end);
            threadGroup[i] = new Thread(new FrequencyWorker(this,start,end,generate,"FrequencyWorker-"+i,wordMap));
            threadGroup[i].start();
        }
        for(int i=0;i<threads;i++){
            threadGroup[i].join();
        }
        System.out.println("Second multi-thread step finished");
    }catch(Exception e){
        System.out.println(e.getMessage());
    }
    System.out.println("Starting coordinate generators");
    threadGroup = new Thread[threads];
    try{
        System.out.println(generate.getSize()+" objects in "+threads+" threads");
        for(int i=0;i<threads;i++){
            int start=(generate.getSize()/threads)*i;
            int end=((generate.getSize()/threads)*(i+1))-1;
            if(i==threads-1){
                end=generate.getSize();
            }
            System.out.println("Start: "+start+" end: "+end);
            threadGroup[i] = new Thread(new CoordinateGenerator(this,start,end,generate,"FrequencyWorker-"+i,wordMap));
            threadGroup[i].start();
        }
        for(int i=0;i<threads;i++){
            threadGroup[i].join();
        }
        System.out.println("Third multi-thread step finished");
    }catch(Exception e){
        System.out.println(e.getMessage());
    }
}

这给了我例外:

  

线程“Thread-5”中的异常java.lang.NullPointerException

     

at semanticobjects.WordMapper.run(WordMapper.java:21)

     

在java.lang.Thread.run(Thread.java:695)

与9和13相同。两者都是在使用threads = 4运行时不应该首先生成的数字。结果计算也是正确的。我刚刚得到这个例外。有什么想法吗?

2 个答案:

答案 0 :(得分:0)

从Java 5开始,有一个新的(不是那么新的)包:java.util.concurrent。在该软件包中,有许多工具可以让您在使用多线程时更加简单。特别是有几种方法可以获得开箱即用的线程池。查看Executors类API和ExecutorService类API。阅读可用的ExecutorService的各种实现。它需要一些习惯,但是一旦掌握了这个概念,它就会消除线程管理的所有繁琐工作,而你所要做的就是担心你的实现逻辑。它还使您的代码更简单,更清洁。

答案 1 :(得分:0)

如果您查看Thread.class,您将看到以下代码:

    public Thread(ThreadGroup group, Runnable target) {
          init(group, target, "Thread-" + nextThreadNum(), 0);
    }

    /* For autonumbering anonymous threads. */
    private static int threadInitNumber;
    private static synchronized int nextThreadNum() {
        return threadInitNumber++;
    }

正如您所看到的,每次创建新线程时,它都将具有使用静态字段threadInitNumber创建的唯一名称 - 请记住,静态字段在给定类的所有实例之间共享。

你的threadCount=4意味着你将同时创建4个主题,但你正在做几次,3个确切地说,3x4等于12个 - 这就是创建&#34; ghost&#的原因34;你认为线程。您正在创建12个线程而不是4个但不能一次创建。现在为什么三线程被命名为13?好吧,因为你的应用程序的其余部分必须在调用generateCoordinatesMultiThread

之前创建了新的线程