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();
 
 
posted @ 2012-05-09 15:19  highriver  阅读(3137)  评论(0编辑  收藏  举报