-1

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

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程序在运行时抛出。小鸡变量 c 的值是否不会在线程 1 和线程 2 堆栈上共享。我知道我犯了一个非常愚蠢的错误,但很困惑。任何指针都会有所帮助。

4

3 回答 3

3

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

c= new Chicks();

进入构造函数,例如

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

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

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

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

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

static Chicks c;
于 2013-08-11T18:39:57.140 回答
1

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

我认为您应该将 go 方法更改为这样的方法

void go(){
  c= new Chicks();
  new Thread(this).start();
  new Thread(this).start();
}
于 2013-08-11T18:50:56.827 回答
0

程序在运行时抛出 NullPointerException。小鸡变量 c 的值是否不会在线程 1 和线程 2 堆栈上共享。

计算机中的任何事情都不会立即发生。如果你相信任何事情都是即时的,那就忘记吧。这意味着虽然一个线程可以更新一个字段,但它需要时间才能对其他线程可见。

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

于 2013-08-11T18:40:07.460 回答