Java:多线程访问主线程变量/方法

Java:多线程访问主线程变量/方法,java,multithreading,inheritance,Java,Multithreading,Inheritance,我正在测试下面的代码,我想知道为什么线程可以访问增量方法 我这么想是因为thread1和thread2是从一个匿名类创建的对象,它不继承工人类。它们如何访问increment()方法?背后的理论是什么 public class Worker { private int count = 0; public synchronized void increment() { count++; } public void run() {

我正在测试下面的代码,我想知道为什么线程可以访问增量方法

我这么想是因为thread1和thread2是从一个匿名类创建的对象,它不继承工人类。它们如何访问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;
公共同步的无效增量(){
计数++;
}
公开募捐{
Thread thread1=新线程(new Runnable(){
公开募捐{
对于(int i=0;i<10000;i++){
增量();
}
}
});
thread1.start();
Thread thread2=新线程(new Runnable(){
公开募捐{
对于(int i=0;i<10000;i++){
增量();
}
}
});
thread2.start();
试一试{
thread1.join();
螺纹2.连接();
}捕捉(中断异常e){
//TODO自动生成的捕捉块
e、 printStackTrace();
}
System.out.println(“计数为:“+Count”);
}
}

由于
可运行的
是非静态的内部类,
工作者。此
隐式继承到可运行实例中。所以真正发生的是

public void run(){
   Worker.this.increment();
}

如果类是静态的,就不会是这种情况。

因为它是一个非静态的内部类,所以它捕获了对创建它的
Worker
实例的引用。这意味着您可以在匿名类内调用worker的方法。

匿名内部类可以访问封闭的类实例字段和方法。简而言之,内部类的每个实例都精确地保留对封闭类的引用,以便它能够访问其字段。如果您想了解有关内部类、静态类等的更多信息。。。查看有关该主题(嵌套类)的Java教程,网址为:
此外,请确保了解与非静态内部类相关的危险,因为如果将对内部实例的引用分发到封闭类之外的代码中,它们可能会带来麻烦并造成内存泄漏。

中描述了“理论”。实践是,内部类构造函数有一个隐藏参数,该参数引用外部类实例,该参数保存在一个隐藏字段中。可以使用
Worker访问此字段。此
构造来自内部类方法。

Java语言规范(JLS)对此进行了说明

内部类包括本地类(§14.3)、匿名类(§15.9.5)和 非静态构件类别(§8.5)

如果O是内部类,则内部类C是O类的直接内部类 C的立即词汇封闭类与C的声明 不会在静态上下文中发生

最后

任何包含词汇的实例(§8.1.3)可通过 明确限定关键字
this

设C是由
ClassName
表示的类。设n是一个整数,使得 C是类的第n个词汇封闭类,其中 此时将显示此表达式

类名称形式的表达式的值。这是第n个 在词汇上包含此
的实例

这就是为什么您可以访问
Worker
的成员

电话

new Runnable()
Worker
实例方法中,为
Worker
创建一个内部类。因此,
Worker
是该
Runnable
的第0个词汇封闭类。对于上面的JLS引号,将
ClassName
替换为
Worker
,您就可以访问您的方法了

Worker.this.increment()


这是由编译器隐式完成的

匿名类引用其封闭类。这意味着匿名类始终被视为内部类?是的,JLS明确指出,
内部类包括本地、匿名和非静态成员类