3

我正在测试以下代码,我想知道线程如何访问增量方法?

我在想这个,因为 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);
    }
}
4

5 回答 5

4

由于Runnables 是非静态内部类,因此Worker.this隐式继承到 Runnable 实例中。所以真正发生的是

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

如果该类是静态的,则情况并非如此。

于 2013-09-26T17:09:03.770 回答
3

Java 语言规范 (JLS) 对内部类和封闭实例进行了说明

内部类包括本地(§14.3)、匿名(§15.9.5)和非静态成员类(§8.5)。

以及关于内部类和封闭实例

如果 O 是 C 的直接词法封闭类并且 C 的声明不在静态上下文中,则内部类 C 是类 O 的直接内部类。

最后是关于合格的this

任何词法封闭的实例(第 8.1.3 节)都可以通过显式限定关键字来引用this

令 C 为 表示的类ClassName。令 n 是一个整数,使得 C 是出现限定 this 表达式的类的第 n 个词法封闭类。

形式表达式的值ClassName.this是 的第 n 个词法封闭实例this

这就是为什么您可以访问Worker.

通话

new Runnable()

Worker实例方法中,为Worker. Workerthat 的第 0 个词法封闭类也是如此Runnable。关于上面的 JLS 报价,替换ClassNameWorker并且您可以访问您的方法

Worker.this.increment()

它是由编译器隐式完成的

于 2013-09-26T17:21:21.487 回答
1

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

于 2013-09-26T17:10:53.143 回答
0

“理论”在内部类中描述。实践是,内部类构造函数具有引用外部类实例的隐藏参数,并且该参数保存在隐藏字段中。可以使用Worker.this内部类方法的构造访问此字段。

于 2013-09-26T17:12:50.543 回答
0

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

于 2013-09-26T17:09:17.070 回答