从另一个线程调用时变量为空
Variable is null when called from another thread
请向我解释变量的奇怪行为。
从主线程创建一个class"B"的实例。
从父"A"的构造函数调用class"B"的抽象函数"init"。
它初始化 debugPaint class "B" 的成员。
然后,它创建一个线程,周期性地调用函数postDraw。
问题是,如果我分配 private volatile Paint debugPaint=null 函数 postDraw 接收 debugPaint 成员作为 空。尽管正如我在调试器中看到的那样,初始化之前是成功的。
如果未完成对 null 的赋值,则一切正常。
private volatile Paint debugPaint;
有什么问题?
p.s 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);
}
}
我认为这里的问题是在构造函数中声明了新的线程(虽然是间接的),所以当新线程启动时A没有完全实例化。
在Java中,不建议从构造函数启动线程。相反,应该在构建之后调用 init()。应该可以吧
见Java: starting a new thread in a constructor
你的问题与线程无关
下面的例子是演示问题的完整程序:
当 main()
例程创建一个新的 B 实例时,它首先调用 A() 构造函数。该构造函数调用 B.init() 将 debugPaint 设置为指向新的 Paint 对象。然后,在 A() 构造函数完成后,调用 default 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());
}
}
请向我解释变量的奇怪行为。 从主线程创建一个class"B"的实例。 从父"A"的构造函数调用class"B"的抽象函数"init"。 它初始化 debugPaint class "B" 的成员。
然后,它创建一个线程,周期性地调用函数postDraw。 问题是,如果我分配 private volatile Paint debugPaint=null 函数 postDraw 接收 debugPaint 成员作为 空。尽管正如我在调试器中看到的那样,初始化之前是成功的。 如果未完成对 null 的赋值,则一切正常。 private volatile Paint debugPaint; 有什么问题?
p.s 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);
}
}
我认为这里的问题是在构造函数中声明了新的线程(虽然是间接的),所以当新线程启动时A没有完全实例化。
在Java中,不建议从构造函数启动线程。相反,应该在构建之后调用 init()。应该可以吧
见Java: starting a new thread in a constructor
你的问题与线程无关
下面的例子是演示问题的完整程序:
当 main()
例程创建一个新的 B 实例时,它首先调用 A() 构造函数。该构造函数调用 B.init() 将 debugPaint 设置为指向新的 Paint 对象。然后,在 A() 构造函数完成后,调用 default 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());
}
}