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 编码经验,但 thread
和 dynamic
与 static
对我来说仍然很陌生。为了让线程正常执行,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";
}
}
}
我的代码的相关总结是这样的:
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 编码经验,但 thread
和 dynamic
与 static
对我来说仍然很陌生。为了让线程正常执行,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";
}
}
}