繁体   English   中英

从另一个线程调用时,变量为null

[英]Variable is null when called from another thread

请向我解释该变量的奇怪行为。 从主线程创建类“ B”的实例。 在父级“ A”的构造函数中,该类称为“ B”类的抽象函数“ init”。 它初始化类“ B”的debugPaint成员。

然后,它创建一个线程,该线程定期调用函数postDraw 问题是,如果我分配了私有易失性Paint debugPaint = null函数postDraw, 则将debugPaint成员接收为null 尽管正如我在调试器中看到的那样,初始化之前已成功完成。 如果未完成对null的赋值,则一切正常。 专用volatile Paint debugPaint ; 问题是什么?

ps init和postDraw之间的时间很长,只有几秒钟。

public class A{

  public A()
  {
    init();
  }

  public void draw(Canvas canvas)
  {
    //some code....
   postDraw(canvas);
  }

  abstract public void postDraw(Canvas canvas);
  abstract public void init();
}


public class B extends A{

    private volatile Paint  debugPaint=null;//=null problem! not =null ok!

    @Override
    public void init()
    {
        debugPaint=new Paint();
    }


    @Override
    public void postDraw(Canvas canvas)
    {
       canvas.drawRect(0,0,128,128,debugPaint);
    }
}

您的问题与线程无关。

下面的示例是一个完整的程序,演示了此问题:

main()例程创建一个新的B实例时,它首先调用A()构造函数。 该构造函数调用B.init(),该函数将debugPaint设置为指向新的Paint对象。 然后,在A()构造函数完成之后,将调用默认的 B()构造函数。

class Paint {
}

class Canvas {
}

abstract class A{

  public A()
  {
    System.out.println("A.<init>() entered");
    init();
    System.out.println("A.<init>() exit");
  }

  public void draw(Canvas canvas)
  {
    //some code....
   postDraw(canvas);
  }

  abstract public void postDraw(Canvas canvas);
  abstract public void init();
}


class B extends A{

    private volatile Paint  debugPaint=null;   //this assignment happens in the default B() constructor

    @Override
    public void init()
    {
        System.out.println("B.init() entered");
        debugPaint=new Paint();
        System.out.println("B.init() exit");
    }


    @Override
    public void postDraw(Canvas canvas)
    {
       System.out.println("debugPaint=" + debugPaint);
    }
}

public class Foobar {
    public static void main(String[] args) {
        B b = new B();
        b.draw(new Canvas());
    }
}

我认为这里的问题是新线程在构造函数中声明(尽管是间接地),所以当新线程启动时A不会完全实例化。

在Java中,建议不要从构造函数启动线程。 相反,应在构造后调用init()。 那应该可以。

请参阅Java:在构造函数中启动新线程

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM