我对以下程序的输出感到困惑
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的值。我知道我犯了一个非常愚蠢的错误,但很困惑。任何指针都会有所帮助。
答案 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。我会确保你有最新的版本