Java Synchronized 和 Static 关键字的总结与使用

来源:互联网 发布:淘宝企业店铺过户 编辑:程序博客网 时间:2024/05/20 13:08

一、Synchronized 同步锁的使用与注意事项
synchronized的4种用法
Synchronized即同步锁,主要应用在多线程之间同步作用,下面是Synchronized的四种使用方法。
1.方法声明时使用,放在范围操作符(public等)之后,返回类型声明(void等)之前.即一次只能有一个线程进入该方法,其他线程要想在此时调用该方法,只能排队等候,当前线程(就是在synchronized方法内部的线程)执行完该方法后,别的线程才能进入.
例如:

  public synchronized void synMethod() {    //方法体,多线程之间会排队调用改方法,防止同时调用产生数据错乱  }

2.对某一代码块使用,synchronized后跟括号,括号里是变量,这样,一次只有一个线程进入该代码块。相当于案例(1)的扩展,案例(1)是对方法加锁,案例(2)是对某一段代码进行加锁处理,原理相同.例如:

  public int synMethod(int a1){    synchronized(a1) {      //一次只能有一个线程进入该代码    }  } 

3.相较于synchronized(“对象”) 、synchronized(“类名”) 、synchronized(“变量”);都是一类,只不过钥匙的作用范围不一样。首先要明白synchronized代码块就像一道门,括号里面的实例就像一把钥匙,线程就如同要开门的人,人要开门只能拿到对应的钥匙才能打开这扇门,其他人则被关在外面。当他要离开这扇门之后就必须把钥匙还出去,别人或者他想再次进入这个们则需要重新借这钥匙。则借钥匙的原则是普通情况下钥匙的使用原则是:“随用随借,用完即还。”
Java语言的关键字,当它用来修饰一个方法或者一个代码块的时候,能够保证在同一时刻最多只有一个线程执行该段代码。

 一、当两个并发线程访问同一个对象object中的这个synchronized(this)同步代码块时,一个时间内只能有一个线程得到执行。另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块。 二、然而,当一个线程访问object的一个synchronized(this)同步代码块时,另一个线程仍然可以访问该object中的非synchronized(this)同步代码块。 三、尤其关键的是,当一个线程访问object的一个synchronized(this)同步代码块时,其他线程对object中所有其它synchronized(this)同步代码块的访问将被阻塞。 四、第三个例子同样适用其它同步代码块。也就是说,当一个线程访问object的一个synchronized(this)同步代码块时,它就获得了这个object的对象锁。结果,其它线程对该object对象所有同步代码部分的访问都被暂时阻塞。 五、以上规则对其它对象锁同样适用.

synchronized的使用方法

二、静态代码块的使用
1、static的使用场景分为静态变量,静态方法,以及静态代码块。静态变量和静态方法的使用,开发中很常见了,就一一赘述了。下面主要探讨下静态代码块、
public class Test {
static {
System.out.println(“我是静态块”);
}
}
如上一个静态代码块,想要搞清除静态代码块的应用,就必须知道类加载的流程。一般而言,new 一个类,首先需要把类代码写进内存,然后在从cpu对话运行类,得到类对象。而静态代码块是在类代码写进内存时就执行了。也就是说这个类在被加载到销毁,静态代码块只会被执行一次,只会不管类对象怎么处理都不会再执行静态代码块。这样就方便我们执行一些只需要初始化一次的数据。如初始化桌面应用的包名赋值给Map时,常用静态代码块。如:

private static final List<Class<? extends Badger>> BADGERS = new LinkedList<Class<? extends Badger>>();static {    BADGERS.add(AdwHomeBadger.class);    BADGERS.add(ApexHomeBadger.class);    BADGERS.add(DefaultBadger.class);    BADGERS.add(NewHtcHomeBadger.class);    BADGERS.add(NovaHomeBadger.class);    BADGERS.add(SonyHomeBadger.class);    BADGERS.add(AsusHomeBadger.class);    BADGERS.add(HuaweiHomeBadger.class);    BADGERS.add(OPPOHomeBader.class);    BADGERS.add(SamsungHomeBadger.class);    BADGERS.add(ZukHomeBadger.class);    BADGERS.add(VivoHomeBadger.class);    BADGERS.add(ZTEHomeBadger.class);    BADGERS.add(EverythingMeHomeBadger.class);}这里通过静态代码块加载List集合的包名,这些包名是不需要在修改的。其次:public class Test {public Test() {// 构造方法        System.out.println("我是构造方法,创建对象的时候我会执行,我执行完,对象就造出来了");}static {    System.out.println("我是静态块,类加载的时候我就执行了,而且只执行这一次");}}当我们new Test()你会发现首先打印出静态块的信息,然后才打印出构造方法信息,然后再次new Test();的时候,只打印出了构造方法的信息,这个例子证明了我上面说的是对的!明白静态代码块调用的顺序就知道他的作用了。
原创粉丝点击