线程 - 为什么在运行时抛出异常?

时间:2013-08-11 18:34:26

标签: java multithreading

我对以下程序的输出感到困惑

public class ChicksYack implements Runnable {
  Chicks c ;
  public static void main(String[] args){
    new ChicksYack().go();
  }

  void go(){
    c= new Chicks();
    new Thread(new ChicksYack()).start();
    new Thread(new ChicksYack()).start();
  }

  public void run() {
    c.yack(Thread.currentThread().getId());
  }
}

class Chicks{
  synchronized void yack(long id){
    for(int x = 1 ; x < 3 ; x++){
      System.out.print(id + " ");
      Thread.yield();
    }
  }
}

程序在运行时抛出NullPointerException。是否会在thread-1和thread-2堆栈上共享Chicks变量c的值。我知道我犯了一个非常愚蠢的错误,但很困惑。任何指针都会有所帮助。

3 个答案:

答案 0 :(得分:3)

如果您确保Chicks的每个实例中都有ChicksYack的实例,那么您需要移动该行:

c= new Chicks();

进入构造函数,例如

public ChicksYack() {
    c= new Chicks();
}

并将成员变量的类型从Chicks c更改为final Chicks c;否则你不能保证你会在线程中完全看到它。添加final keywoard可确保:

  

构造函数退出时,最终字段的值保证对访问构造对象的其他线程可见。 (参考:Javamex.com网站)

原样,您正在创建另外两个ChicksYack未初始化c成员的实例。

现在,如果您打算在Chicks的所有实例之间只共享一个ChicksYack个实例,那么您需要将其声明为static,例如

static Chicks c;

答案 1 :(得分:1)

你有三个ChicksYack实例和Chicks的非静态字段。

我认为你应该将go方法改为像这样的东西

void go(){
  c= new Chicks();
  new Thread(this).start();
  new Thread(this).start();
}

答案 2 :(得分:0)

  

程序在运行时抛出NullPointerException。是否会在thread-1和thread-2堆栈上共享Chicks变量c的值。

计算机中的任何内容都不会立即发生。如果你相信任何事情都是即时的,那就忘了。这意味着虽然线程可以更新字段,但是其他线程可以看到它需要时间。

有许多例外,一个是使用volatile字段(它仍然不是即时而是等待任何更新),另一个是在线程启动之前设置的任何字段。如果这个程序真的为你抛出一个NPE,我会怀疑你的JVM中有一个bug。我会确保你有最新的版本