zoukankan      html  css  js  c++  java
  • Static块与线程安全

    每一次通过命令行执行java class就会做一次类加载。假如类变量是一个UUID的串,每一次java class都不一样。

    类变量和static块仅在类第一次加载执行一次。类加载之后,才会有实例化。所以可以理解为每一次类的实例化只有第一次实例化的时候,会导致类加载并执行static块,其它的都不会执行static块

     
    static块的场景:用来初始化一些对所有实例都有用的公共数据结构。
     
    结论:static块中的操作是线程安全的,类加载的阶段还没有实例被创建,也就不存在实例的线程中修改类变量的情况存在。也不会存在jvm中相同的类加载多次。

     

    类变量什么时候不是线程安全的呢?
    当类加载完成,static块执行完毕后,开始实例化多个对象,而这些对象都可以修改static变量。这个时候,需要同步。

     

    示例1.weibo的配置初始化不需要同步

        static
        {
            final String CLIENT_ID = "×××××";
            final String CLIENT_SERCRET = "××××××××××××××××××";
            final String BASEURL = "https://api.weibo.com/2/";
            final String ACCESSTOKENURL = "https://api.weibo.com/2/oauth2/access_token";
            final String AUTHORIZEURL = "https://api.weibo.com/2/oauth2/authorize";
    
            WeiboConfig.updateProperties("client_ID", CLIENT_ID);
            WeiboConfig.updateProperties("client_SERCRET", CLIENT_SERCRET);
            WeiboConfig.updateProperties("baseURL", BASEURL);
            WeiboConfig.updateProperties("accessTokenURL", ACCESSTOKENURL);
            WeiboConfig.updateProperties("authorizeURL", AUTHORIZEURL);
        };

     

     

    示例2:下面的map写入不需要同步,因为对于enum,这个map其时只会在类加载的时候写一次。以后都是只读的操作。所以不存在同步。

    public enum TestEnum {
    
        T11("1", "1"), T12("1", "2"),T21("2","1");
        public static Map<String, List<TestEnum>> map = new HashMap<String, List<TestEnum>>();
        static
        {
            System.out.println("static init begin");
            for (TestEnum test : EnumSet.allOf(TestEnum.class))
            {
                if(map.get(test.getKey())!=null){
                    map.get(test.getKey()).add(test);
                }else{
                    List<TestEnum> list=new ArrayList<TestEnum>();
                    list.add(test);
                    map.put(test.getKey(),list);
                }
            }
            System.out.println("static init end");
        }
            private String key;
        private String val;
    
        private TestEnum(String key, String val)
        {
            this.key = key;
            this.val = val;
        }
    
        public String getKey()
        {
            return key;
        }
    
        public void setKey(String key)
        {
            this.key = key;
        }
    
        public String getVal()
        {
            return val;
        }
    
        public void setVal(String val)
        {
            this.val = val;
        }
        
        public static  List<TestEnum> getTestEnumBy(String key){
            return map.get(key);
        }
    
    }
     
     
     Static除了修饰静态变量方法之外,还可以用来修改内部类,修改内部类的好处是实例化写起来方便。如果需要回调嵌套类的实例化方法,则不能使用static修饰。
     
    A类有个叫B的内部类(非静态)
    A  a= new A();
    a.B b = new a.B();
    b就是B的一个对象。

    假如B是内部静态类:
    A.B b= new A.B();
     
     
  • 相关阅读:
    CF1056G
    mysql xtrabackup 备份恢复
    linux yum源配置
    mysql 第24章 优化
    mysql 第23章 监控
    mysql 第22章 高可用MMM、MHA
    mysql 第21章 集群
    mysql 第20章 复制
    mysql 第19章 备份恢复
    mysql 第18章 导入导出
  • 原文地址:https://www.cnblogs.com/highriver/p/2491845.html
Copyright © 2011-2022 走看看