Java Class装载时的问题

上代码

public class DoSome {
    private static final DoSome instance = new DoSome();

    private DoSome(){
        System.out.println("ready");
        CountDownLatch await = new CountDownLatch(1);
        doing();
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("thread ready");
                doing();
                await.countDown();
            }
        }).start();

        try {
            await.await(10000, TimeUnit.MILLISECONDS);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("done");
    }

    private static void doing() {
        System.out.println("doing");
    }

    public static void main(String[] args) {
    }
}

运行主方法得到结果如下

ready
doing
thread ready
// 中间阻塞了10s
done
doing

问题分析

在装载DoSome时,因为我们存在 static final DoSome instance = new DoSome();,会去执行构造函数。当前构造函数中可以执行doing(),线程中也可以输出代码,但是当线程执行到doing()的时候,阻塞了。直至await结束了之后(可能是类的装载完成了),线程才可以执行doing()

猜测

所以当Class没有装载完成时,其他线程是无法访问当前Class的静态方法?

阅读 1.8k
2 个回答

是的,Java要求类加载是同步的,同一个类不能同时加载

不是。

错误1:直至await结束了之后(可能是类的装载完成了),线程才可以执行doing()

这个是因为,你那边设置了时间,如果直接用await.await();你会发现控制台已经在等待,没有输出done和doing

错误2。所以当Class没有装载完成时,其他线程是无法访问当前Class的静态方法

static方法,是存在方法区的,对象是在堆中,所以和对象是否创建没有关系。请看下面的例子,控制台先输出ready,然后休眠3秒,这个时候,类还没创建好,此时我另外一个线程,在一秒后会输出doing,再过一下,输出done。

原因是因为死锁了(我也不知道为什么死锁了,有人知道请告知我),怎么找死锁,请参考这篇文章

public class DoSome1 {

    private DoSome1(){
        System.out.println("ready");
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("done");
    }

    private static void doing() {
        System.out.println("doing");
    }

    public static void main(String[] args) throws InterruptedException {
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(1000);
                    DoSome1.doing();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }).start();
        DoSome1 instance = new DoSome1();

    }
}
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏