2011-12-10 31 views
0

我想了解一个Thread对象状态的线程完成后后。我读过一本书,一旦线程完成其run()方法,线程对象仍然是头上的有效对象,仍然可以用作实例对象,您仍然可以调用它的方法。我决定尝试以下示例:运行线程的run()方法的线程已经完成

class DieThread implements Runnable{ 

    int y = 0; 

    public void run(){ 
     for(int x=0; x<100; x++){ 
      System.out.println("    " + Thread.currentThread().getName()); 
      System.out.println("y is " + y); 
      y++; 
      System.out.println("y is " + y); 
     } 
    } 
} 

class ZiggyTest2{ 
    public static void main(String[] args){  

     DieThread d = new DieThread(); 

     Thread a = new Thread(d); 
     Thread b = new Thread(d); 
     Thread c = new Thread(d); 

     a.start(); 
     b.start(); 
     c.start(); 

     try{ 
      a.join(); 
      b.join(); 
      c.join(); 
     }catch(Exception e){ 
      System.out.println(e); 
     } 

     System.out.println("Running C's Run"); 
     c.run();   
    } 
} 

main()通过使用join()等待其他3个线程完成。然后调用c的run()方法,但由于某种原因,它不会从run()方法中打印任何内容。这是我运行上述程序后输出的最后几行。

y is 287 
y is 287 
y is 288 
y is 289 
      Thread-1 
      Thread-0 
y is 289 
y is 289 
y is 290 
y is 291 
      Thread-1 
      Thread-0 
y is 291 
y is 291 
y is 292 
y is 293 
      Thread-1 
      Thread-0 
y is 293 
y is 293 
y is 294 
y is 295 
      Thread-0 
y is 295 
y is 296 
      Thread-0 
y is 296 
y is 297 
      Thread-0 
y is 297 
y is 298 
      Thread-0 
y is 298 
y is 299 
      Thread-0 
y is 299 
y is 300 
Running C's Run 

即使线程已经完成,我期待y因为c.run()调用的值为400。

任何想法?

谢谢

+1

你确定你不想叫d.run()?此外,我很惊讶没有破坏,因为你有3个线程递增相同的变量,没有锁定。 – Thomas

+0

是的,我想在完成后运行线程对象。 – ziggy

回答

1

的理由让你在观察什么是埋在Thread的实施状况后null类。

当您致电c.run()时,您正在调用线程对象的run方法。这被指定为调用target对象的run方法(即,在Thread构造提供的可运行的),如果它不是null。如果targetnull那么Thread.run()方法不起作用。

OK,所以你提供一个非空target

事实上,当一个Thread完成时,Thread.exit()方法被调用来清理。而清理所做的其中一件事是将null分配到target。 (该代码有一条关于需要积极清除引用的注释以及一个缺陷ID,但遗憾的是缺少相应的缺陷报告,因此无法知道它们的真实原因。)

无论如何,底线是你不能通过调用Thread.run()重新运行目标对象的run()方法。但是你可以直接调用目标对象的run()方法...如果你有目标引用。

+0

如果Thread.exit将为目标赋予null,那么不会调用目标的run方法会导致NullPointerException?我只是在线程完成后尝试调用d.run(),但没有得到NullPointerException,即使此时该对象应该为空。 – ziggy

+0

你不会得到一个NPE。再次阅读我的第二段...特别是关于'target'为'null'的情况。更好的是,你自己来看看Thread类的源代码。 –

+0

*所以不可能知道他们这样做的真正原因* >> Stephen,自从Oracle接管后,它的bug从1.0.2开始,他们删除了很多bug引用。我清楚地记得在1999年的代码,仍然是一样的。无论哪种方式,由于线程泄漏和其他原因,积极的删除帮助gc。现在它仍然很酷,因为有时线程仍然泄漏。 – bestsss

3

如果扩展Thread类,它会工作。现在,检查Runnable目标这Thread.exit()

1

同步访问对象DieThread

synchronized(this) { 
    System.out.println("    " + Thread.currentThread().getName()); 
    System.out.println("y is " + y); 
    y++; 
    System.out.println("y is " + y); 
} 
+0

谢谢。我并不是很担心对象的状态。我对线程完成线程后发生的事情更感兴趣。 – ziggy

相关问题