【问题标题】:Java spawning Ghost ThreadsJava 产生幽灵线程
【发布时间】:2016-09-28 15:10:14
【问题描述】:

我正在研究一种新的 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 中的异常

在语义对象.WordMapper.run(WordMapper.java:21)

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

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

【问题讨论】:

  • 请指出哪一行抛出异常 - 标记WordMapper.java:21
  • 是什么让你认为这些头巾是鬼线?如果它是线程号,请注意这个数字只是一个增加的静态 int,即如果你重新运行该方法,数字会更大(并且 Thread-1 可能是主线程,所以 4 个新线程应该命名为 Thread -2 到线程 5)。如果您希望线程在再次调用该方法时具有相同的名称,请为构造函数提供名称。
  • @SirTobiSwobi 但老实说,使用ExecutorService 和Callable 任务会更简单。

标签: java multithreading exception


【解决方案1】:

从 Java 5 开始,有一个新的(不是那么新的)包:java.util.concurrent。在该软件包中,有很多工具可以让您在使用多线程时变得更加简单。特别是有几个选项可以获得开箱即用的线程池。查看Executors 类API 和ExecutorService 类API。阅读有关可用的 ExecutorService 的各种实现。这需要一点时间来适应,但是一旦你掌握了这个概念,它就会带走所有繁琐的线程管理工作,你所要做的就是担心你的实现逻辑。它还使您的代码更简单、更清晰。

【讨论】:

    【解决方案2】:

    如果您查看 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 - 这就是您认为创建“幽灵”线程的原因。您正在创建 12 个线程而不是 4 个线程,但不是一次。现在为什么线程被命名为 13 而不是 12?好吧,因为您的应用程序的其余部分必须在调用 generateCoordinatesMultiThread 之前创建了新线程

    【讨论】:

      猜你喜欢
      • 2016-08-19
      • 1970-01-01
      • 1970-01-01
      • 2018-06-16
      • 2011-07-09
      • 2014-07-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多