Java: 从线程操作非静态变量?

Java: Manipulating non-static variable from thread?

我的代码的相关总结是这样的:

public class A {
    String aString;

    public static void main(String[] args) {
        B b = new B();
        new Thread(b).start();
    }
    public static class B implements Runnable {
        public void run() {
            aString = "foo";
        }
    }
}

我有几个月的 Java 编码经验,但 threaddynamicstatic 对我来说仍然很陌生。为了让线程正常执行,classB 必须是静态的,否则只有线程执行,而不是两者都执行。我的目标显然是让线程在后台执行,以便我在 class A 中可能拥有的其他代码可以同时执行。问题是,如果 class B 是静态的,我无法操作字符串 aString,因为我得到异常 non-static variable aString cannot be referenced from a static context.

我已经查找了这方面的信息,但我没有找到任何与解决线程中的这个问题相关的信息。我的问题是,我如何在 class B 内操作 aString 并仍然让线程正常工作(classes 运行,而不仅仅是 class B )?

为了使您的示例工作,您需要这样的东西:

public class A {
    volatile String aString;

    public static void main(String[] args) throws InterruptedException {
        A a = new A();
        Thread t = new Thread(a.new B());
        t.start();
        t.join(); // wait for t to finish
        System.out.println(a.aString); // prints "foo"
    }

    class B implements Runnable {
        public void run() {
            aString = "foo";
        }
    }
}

解决 static 问题很简单 - 请参阅代码了解具体方法。

我希望其余代码有助于说明您在使用线程时需要注意的一些问题。

B 是静态的,所以只存在于 class 级别,因此看不到其父 class

的实例变量
public class A {
    String aString;  // <== instance variable

    public static void main(String[] args) {
        B b = new B();
        new Thread(b).start();
    }
    public static class B implements Runnable {  // <== static class
        public void run() {
            aString = "foo";
        }
    }
}

可能的修复。也使 aString 静态化

public class A {
    static String aString;

可能的修复。使 B 非静态。这是它变得有点奇怪的地方。 B现在只存在于A的实例级别,所以需要先创建一个A实例。

public class A {
    String aString;

    public static void main(String[] args) {
        B b = new A().new B();  // <== need to create an A before a B
        new Thread(b).start();
    }
    public class B implements Runnable {
        public void run() {
            aString = "foo";
        }
    }
}

您要求 class B 的对象实例(您使用 new B() 创建)访问您尚未创建的对象实例的成员变量。在您的代码中,没有创建 class B 的对象。

我认为您可能认为 运行 class A 中的 main() 方法以某种方式实例化 class A 的实例 - 事实并非如此.

以下将起作用,因为您正在创建 A 的实例并将其提供给 B 的实例。

public class A {
    String aString;

    public static void main(String[] args) {
        A a = new A();
        B b = new B(a);
        new Thread(b).start();
    }
    public static class B implements Runnable {
        private final A a;

        public B(A a){
          this.a = a;
        }

        public void run() {
            a.aString = "foo";
        }
    }
}