我正在测试以下代码,我想知道线程如何访问增量方法?
我在想这个,因为thread1和thread2是从匿名类创建的对象,它们不继承worker类,它们如何访问increment()方法?它背后的理论是什么?
public class Worker {
private int count = 0;
public synchronized void increment() {
count++;
}
public void run() {
Thread thread1 = new Thread(new Runnable() {
public void run() {
for(int i = 0; i < 10000; i++) {
increment();
}
}
});
thread1.start();
Thread thread2 = new Thread(new Runnable() {
public void run() {
for(int i = 0; i < 10000; i++) {
increment();
}
}
});
thread2.start();
try {
thread1.join();
thread2.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("Count is: " + count);
}
}
答案 0 :(得分:4)
由于Runnable
是非静态内部类,因此Worker.this
被隐式继承到Runnable实例中。所以真正发生的是
public void run(){
Worker.this.increment();
}
如果这个类是静态的,那就不是这样了。
答案 1 :(得分:2)
Java语言规范(JLS)对Inner Classes and Enclosing Instances
进行了说明内部类包括本地(§14.3),匿名(§15.9.5)和 非静态成员类(第8.5节)。
和about Inner Classes and Enclosing Instances
如果O是,则内部类C是类O的直接内部类 立即词汇封闭C类和C的声明 不会发生在静态环境中。
任何词汇封闭的实例(第8.1.3节)都可以被引用 明确限定关键字
this
。设C为
ClassName
表示的类。设n是这样的整数 C是这个类的第二个词汇封闭类 合格的这个表达式出现了。
ClassName.this
形式的表达式的值是n 词汇封闭this
的实例。
这就是为什么你可以访问Worker
的成员。
电话
new Runnable()
在Worker
实例方法中,为Worker
创建内部类。所以Worker
是Runnable
的第0个词汇封闭类。关于上面的JLS引号,将ClassName
替换为Worker
,您可以访问您的方法
Worker.this.increment()
它由编译器隐式完成
答案 2 :(得分:1)
匿名内部类可以访问封闭的类实例字段和方法。简而言之,内部类的每个实例都精确地保持对封闭类的引用,以便它能够访问其字段。如果您想了解有关内部类,静态类等的更多信息,请查看有关该主题的Java教程(嵌套类): http://docs.oracle.com/javase/tutorial/java/javaOO/nested.html 另外,请确保理解与非静态内部类相关的危险,因为如果将内部实例的引用分发给封闭类之外的代码,它们可能会很麻烦并造成内存泄漏。
答案 3 :(得分:0)
因为它是一个非静态内部类,所以它捕获对其中创建的Worker
实例的引用。这意味着您可以在匿名类中调用worker的方法。
答案 4 :(得分:0)
inner classes中描述了“理论”。实践是,内部类构造函数具有隐藏参数,该参数引用外部类实例,并且该参数保存在隐藏字段中。可以使用内部类方法中的Worker.this
构造访问此字段。