Java:多线程访问主线程变量/方法
我正在测试下面的代码,我想知道为什么线程可以访问增量方法 我这么想是因为thread1和thread2是从一个匿名类创建的对象,它不继承工人类。它们如何访问increment()方法?背后的理论是什么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() {
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明确指出,内部类包括本地、匿名和非静态成员类
。