其他分享
首页 > 其他分享> > 类加载的并发,单例模式,静态资源加载

类加载的并发,单例模式,静态资源加载

作者:互联网

全限定类在同一个类加载器只能加载一次,意味着static对象及代码块只一次,为单例之依据

如果并发发生,则阻塞

 

public class ByLoad {

    static {
        try {
            System.out.println(Thread.currentThread() + " start " + System.currentTimeMillis()/1000 );
            Thread.sleep(20000);  【11行】
            System.out.println(Thread.currentThread() + " end " + System.currentTimeMillis()/1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public static void func() {
        System.out.println(Thread.currentThread() + " func " + System.currentTimeMillis()/1000);
    }
}

 

public class Main {
    public static void main(String []f) {
        CountDownLatch countDownLatch = new CountDownLatch(1);
        for(int i=0; i<3; ++i) {
            int id = i+1;
            Thread thread = new Thread(new MyThread(countDownLatch), "thread - " + id + " haha");
            thread.start();
        }
        countDownLatch.countDown();

    }

    private static class MyThread implements Runnable {

        private CountDownLatch countDownLatch;

        public MyThread(CountDownLatch countDownLatch) {
            this.countDownLatch = countDownLatch;
        }

        @Override
        public void run() {
            try {
                countDownLatch.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            ByLoad.func(); 【35行】
        }
    }
}

 

输出:

Thread[thread - 1 haha,5,main] start 1602256385
Thread[thread - 1 haha,5,main] end 1602256405
Thread[thread - 1 haha,5,main] func 1602256405
Thread[thread - 3 haha,5,main] func 1602256405
Thread[thread - 2 haha,5,main] func 1602256405

 

可以看到线程1执行到ByLoad.func()时,进行ByLoad的加载,静态代码块执行

2 3 线程的ByLoad.func()被阻塞

"thread - 3 haha" #12 prio=5 os_prio=31 tid=0x00007f820199a000 nid=0x4003 in Object.wait() [0x0000700002cf2000]
java.lang.Thread.State: RUNNABLE
at Thread.loader.Main$MyThread.run(Main.java:35)
at java.lang.Thread.run(Thread.java:745)

"thread - 2 haha" #11 prio=5 os_prio=31 tid=0x00007f820003d800 nid=0x4103 in Object.wait() [0x0000700002bef000]
java.lang.Thread.State: RUNNABLE
at Thread.loader.Main$MyThread.run(Main.java:35)
at java.lang.Thread.run(Thread.java:745)

"thread - 1 haha" #10 prio=5 os_prio=31 tid=0x00007f8201837800 nid=0x4203 waiting on condition [0x0000700002aeb000]
java.lang.Thread.State: TIMED_WAITING (sleeping)
at java.lang.Thread.sleep(Native Method)
at Thread.loader.ByLoad.<clinit>(ByLoad.java:11)
at Thread.loader.Main$MyThread.run(Main.java:35)
at java.lang.Thread.run(Thread.java:745)

 

 

3 我们来回看单例模式

饿汉式

1 2 3 4 5 6 7 public class ImageLoader{        private static ImageLoader instance = new ImageLoader;        private ImageLoader(){}        public static ImageLoader getInstance(){              return instance;          }   }

一上来就把单例对象创建出来了,要用的时候直接返回即可

 

这里的“一上来”是有误区的,java的类本来就是懒加载,不存在一上来;

那么为什么还会出来后面的静态代码块式单例模式?

 

试想一下这种情况:

public class ImageLoader{        private static ImageLoader instance = new ImageLoader;        private ImageLoader(){}        public static ImageLoader getInstance(){              return instance;          }     public static void any() {...} }

any() 先于getInstance执行,则不算懒加载了

故:

为了避免意外提前加载,在实际业务代码中才引入静态内部类加固懒加载,而不完全指望公开类懒加载,

单例的静态内部类模式即是如此原理

 

 

类的加载不存在多线程,因为只执行一次,其他线程等着加载线程

 

 

 

6 我们常常碰到静态基础数据加载:

 

标签:java,Thread,并发,static,ImageLoader,单例,public,加载
来源: https://www.cnblogs.com/silyvin/p/13789575.html