2016-09-28 155 views
0

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

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()); 
    } 
} 

这让我异常:在线程

异常 “主题-5” 显示java.lang.NullPointerException

在semanticobjects.WordMapper.run(WordMapper的.java:21)

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

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

+0

请指出whith行引发异常 - 标记'WordMapper.java:21' – Antoniossss

+0

是什么让您认为theads是虚线?如果是线程号,请注意这个数字只是一个增加的静态int,例如,如果您重新运行该方法,数字会更大(并且线程1可能是主线程,所以应该将4个新线程命名为Thread -2到Thread-5)。如果您希望线程在调用该方法时具有相同的名称,请为该构造函数提供一个名称。 – Thomas

+1

@SirTobiSwobi,但说实话,使用ExecutorService和Callable任务会更简单。 – Antoniossss

回答

0

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

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次是准确的,3次4次等于12次 - 这就是在你看来创建“鬼”线程的原因。您正在创建12个线程而不是4个,但不是一次。现在为什么thre线程被命名为13,保证12?那么因为其他应用程序必须在调用之前创建了新线程generateCoordinatesMultiThread