简体   繁体   English

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

[英]Java: Multithreading accessing main thread variables/methods

I was testing the following code, and I was wondering how come the threads could access the the increment method? 我正在测试以下代码,我想知道线程如何访问增量方法?

I was thinking this since thread1 and thread2 are objects created from an anonymous class that don't inherit worker class how can they access the increment() method? 我在想这个,因为thread1和thread2是从匿名类创建的对象,它们不继承worker类,它们如何访问increment()方法? what is the theory behind it? 它背后的理论是什么?

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);
    }
}

Since the Runnable s are non-static inner classes , the Worker.this is implicitly inherited into the Runnable instances. 由于Runnable是非静态内部类,因此Worker.this被隐式继承到Runnable实例中。 So that what is really happening is 所以真正发生的事情是

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

If the class were static this wouldn't be the case. 如果这个类是静态的,那就不是这样了。

The Java Language Specification (JLS) states this about Inner Classes and Enclosing Instances Java语言规范(JLS)声明了关于内部类和封闭实例的内容

Inner classes include local (§14.3), anonymous (§15.9.5) and non-static member classes (§8.5). 内部类包括本地(§14.3),匿名(§15.9.5)和非静态成员类(§8.5)。

and about Inner Classes and Enclosing Instances 以及关于内部类和封闭实例

An inner class C is a direct inner class of a class O if O is the immediately lexically enclosing class of C and the declaration of C does not occur in a static context. 内部类C是类O的直接内部类,如果O是C的直接词汇封闭类,并且C的声明不在静态上下文中发生。

and finally about Qualified this 最后关于合格的this

Any lexically enclosing instance (§8.1.3) can be referred to by explicitly qualifying the keyword this . 任何词汇封闭的实例(第8.1.3节)都可以通过明确限定关键字this来引用。

Let C be the class denoted by ClassName . 设C是ClassName表示的类。 Let n be an integer such that C is the n'th lexically enclosing class of the class in which the qualified this expression appears. 设n是一个整数,使得C是出现限定该表达式的类的第n个词汇封闭类。

The value of an expression of the form ClassName.this is the n'th lexically enclosing instance of this . 该形式的表达式的值ClassName.this是词法包围的实例的第n个this

That's why you can access members of Worker . 这就是为什么你可以访问Worker成员。

The call 电话

new Runnable()

within a Worker instance method, creates an inner class for Worker . Worker实例方法中,为Worker创建一个内部类。 So Worker is the 0'th lexically enclosing class of that Runnable . 因此, WorkerRunnable第0个词汇封闭类。 With regards to the JLS quotes above, replace ClassName with Worker and you have access to your method 关于上面的JLS引号,将ClassName替换为Worker ,您可以访问您的方法

Worker.this.increment()

It's done implicitly by the compiler 这是由编译器隐式完成的

An anonymous inner class has access to the enclosing class instance fields and methods. 匿名内部类可以访问封闭的类实例字段和方法。 In short, every instance of the inner class keeps a reference to the enclosing class precisely so that it is able to access its fields. 简而言之,内部类的每个实例都精确地保持对封闭类的引用,以便它能够访问其字段。 If you want more info about inner classes, static classes, etc... check out the Java Tutorials on that topic (Nested Classes) at: http://docs.oracle.com/javase/tutorial/java/javaOO/nested.html Also, make sure to understand the dangers associated with non-static inner classes, as they can be troublesome and create memory leaks if you hand out references to the inner instance to code outside of the enclosing class. 如果您想了解有关内部类,静态类等的更多信息,请查看有关该主题的Java教程(嵌套类): http//docs.oracle.com/javase/tutorial/java/javaOO/nested。 html另外,请确保理解与非静态内部类相关的危险,因为如果将内部实例的引用分发给封闭类之外的代码,它们可能会很麻烦并产生内存泄漏。

Because it's a non-static inner class, it captures a reference to the Worker instance it is created within. 因为它是一个非静态内部类,所以它捕获对其中创建的Worker实例的引用。 That means you can invoke methods of the worker inside the anonymous class. 这意味着您可以在匿名类中调用worker的方法。

The "theory" is described in inner classes . “理论”在内部类中描述。 The practice is, inner class constructors have hidden parameter which refers to outer class instance, and that parameter is saved in a hidden field. 实践是,内部类构造函数具有隐藏参数,该参数引用外部类实例,并且该参数保存在隐藏字段中。 This field can be accessed with Worker.this construct from inner class methods. 可以使用内部类方法中的Worker.this构造访问此字段。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM