【问题标题】:Multi threading instance field implementation多线程实例字段实现
【发布时间】:2015-05-08 07:03:03
【问题描述】:
public class Chicks {
    synchronized void yacks(long id)
    {
        for(int x = 1; x<3; x++)
        {
            System.out.println(id + " ");
            Thread.yield();
        }
    }
}
class ChickYacks implements Runnable
{
    Chicks c; // No exception if I declare it as static
    public static void main(String[] args) {
        new ChickYacks().go();
    }
    public void run()
    {
        c.yacks(Thread.currentThread().getId()); //Throws a Nullpointer exceptin
    }
    void go()
    {
        c = new Chicks();
        new Thread(new ChickYacks()).start();
        new Thread(new ChickYacks()).start();
    }
}

为什么会在run method() 中抛出 Nullpointer 异常。在我看来一切都很好。当我将Chicks 'c' 声明为静态但我不明白为什么?

【问题讨论】:

  • 请注意,这与多线程无关。您只是在创建对象,忘记为这些对象的字段分配非空值,然后在此空字段上调用方法。

标签: java multithreading scjp ocpjp


【解决方案1】:

您的go 方法为ChickYacks 的“this”实例分配了一个非空值 - 但随后创建了ChickYacks 的两个 实例,每个实例都有一个空值为c

你可以:

  • 改为在构造函数中初始化c,以便每个实例都有一个非空值
  • 在字段初始化器中初始化c
  • run()方法中初始化c
  • go 方法中的 实例初始化c
  • this 传递给Thread 构造函数,而不是创建新实例
  • c 设为静态,这样您从哪个实例访问它都无关紧要(或者实际上是否以静态方法访问它;它将与类型相关联,而不是与实例相关联)

这与线程无关,真的。如果你不使用线程,你会得到同样的效果,只是在原始线程而不是新线程中抛出异常:

void go()
{
    c = new Chicks();
    new ChickYacks().run(); // Bang!
    new ChickYacks().run();
}

【讨论】:

  • 哇!约翰斯基特回答我的问题。它必须 100% 正确:)
  • 此外,我很高兴您回答了我的问题,但我仍然不明白:/“ChickYacks 的“this”实例的非空值”——这是什么意思?
  • @kvp:那你不明白哪一点?我已经扩展了我的答案。 (第二次 - 狡猾的网络连接吃掉了第一次扩展......)
  • 在这种情况下初始化它意味着Chicks c = new Chicks(); 对吗?所以只是因为c' object is null it is throwing NullPointerException`?
  • @kvp:不,因为您在错误的实例中初始化它。您了解实例字段的工作原理吗?当您创建一个新实例时,它具有一组单独的字段...
猜你喜欢
  • 1970-01-01
  • 2013-06-02
  • 2021-08-01
  • 2021-07-23
  • 1970-01-01
  • 1970-01-01
  • 2013-06-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多