oo_*_*_oo 5 java multithreading initialization classloader
让我们假设以下类定义:
public class A {
public final static String SOME_VALUE;
static {
SOME_VALUE = "some.value";
}
}
public class B {
private final String value = A.SOME_VALUE;
}
Run Code Online (Sandbox Code Playgroud)
假设A类尚未加载,当某个线程T实例化B类对象时会发生什么?必须首先加载和实例化A类.但我的问题是:如果它是在线程T的上下文中完成的,或者更确切地说是在其他(特殊)"类加载器"线程的上下文中完成的?
查看JLS的第12.4.1节("初始化发生时")和12.4.2("详细初始化过程"):
初始化类或接口的过程如下:
- 在Class对象上同步(第14.19节),该对象表示要初始化的类或接口.这涉及等到当前线程可以获得该对象的锁定(第17.1节).
- 如果某个其他线程正在对类或接口进行初始化,则等待此Class对象(暂时释放锁定).当前线程从等待中唤醒时,重复此步骤.
- 如果当前线程正在对类或接口进行初始化,那么这必须是初始化的递归请求.释放Class对象上的锁定并正常完成.
- 如果已初始化类或接口,则无需进一步操作.释放Class对象上的锁定并正常完成.
...
规范声明初始化发生在当前线程中(意味着任何线程到达导致需要初始化所讨论的类的状态),但JVM实现必须做出一些非常严格的同步保证以避免任何问题.
没有专门的线程来加载类。它将来自第一次引用该类的线程。ClassLoader.loadClass 方法是同步的,因此尝试加载同一类的多个线程不会相互干扰。
编辑要枚举的代码
public class Arbit {
public static void main(String[] args) throws Exception{
B b1 = new B("1");
B b2 = new B("2");
B b3 = new B("3");
b1.start();
b2.start();
b3.start();
b1.join();
b2.join();
b3.join();
}
}
class B extends Thread{
B(String s){
setName(s);
}
@Override
public void run() {
try {
Thread.sleep(new Random().nextInt(100));
} catch (InterruptedException e) {
}
System.out.println(A.s);
}
}
class A{
static String s = Thread.currentThread().getName();
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
514 次 |
最近记录: |