JAVA多线程之单例模式
2016-01-24 11:20
423 查看
1,饿汉模式代码:
2,懒汉模式代码:
3,懒汉模式中存在的多线程安全性问题
当有多个线程同时执行到if语句判断时:线程A执行if判断 instace==null;CPU切换到线程B执行,线程B执行if判断 instance==null,这样就 new 了两个SingleTest对象。线程B new 的SingleTest对象更改了线程A new 的SingleTest对象的引用。
使用了static 锁进行同步。当有多个线程同时执行到if语句判断时(第一个if语句):线程A执行if判断 instace==null;CPU切换到线程B执行,线程B执行if判断 instance==null。但是只有一个线程能够获得 static 锁进入同步代码块,当第一个线程进入同步代码块后 new 了SingleTest对象,后面的进程再进入同步代码块时,进行if判断为假,就不会再创建第二个SingleTest对象了。
4,饿汉模式与线程安全的懒汉模式比较
①二者都是线程安全的。对于饿汉模式而言,它在JVM加载该类时就已经创建好SingleTest对象了,因此有多个线程调用getInstance()时始终只有一个SingleTest对象存在。
②不管需不需要SingleTest对象,只要一加载SingleTest.java类,就会创建SingleTest对象,比如:假设SingleTest类中还定义了其他静态方法,通过类名.静态方法名() 调用静态方法时,会创建SingleTest对象,尽管此时并不需要使用SingleTest的实例对象。
若创建SingleTest对象开销很大,则有性能问题。而对于懒汉模式而言,只有在需要SingleTest对象时,才会创建,因为它是通过调用getInstance方法,然后在该方法里面new的对象;而对于饿汉模式,SingleTest对象在加载时已经生成,getInstance()方法只是负责返回该对象。
5,其他的一些多线程问题
①static 锁 与 this 锁
静态同步方法与同步方法 使用的锁
静态同步方法使用的是static锁。调用静态同步方法相当于获得了一个以 类名.class 的锁,如下:
同步方法使用的是this锁。调用同步方法相当于获得了一个当前对象的锁。因为对于方法而言,是通过 对象.方法名进行调用的,即该方法被调用时,一定是某个对象调用了它,同步方法就获得了该对象的锁,如下:
②线程执行了Thread.sleep(long)方法时,不会释放它所占有的锁。(注意:没有不带参数的sleep()方法)
多线程入门资料参考:JAVA 多线程编程深入详解--汪文君
public class SingleTest { private static SingleTest instance = new SingleTest(); private SingleTest(){ } public SingleTest getInstance(){ return instance; } }
2,懒汉模式代码:
public class SingleTest { private static SingleTest instance = null; private SingleTest(){ } public SingleTest getInstance(){ if(null == instance) instance = new SingleTest(); return instance; } }
3,懒汉模式中存在的多线程安全性问题
当有多个线程同时执行到if语句判断时:线程A执行if判断 instace==null;CPU切换到线程B执行,线程B执行if判断 instance==null,这样就 new 了两个SingleTest对象。线程B new 的SingleTest对象更改了线程A new 的SingleTest对象的引用。
if(null == instance) instance = new SingleTest();改进:
public class SingleTest {
private static SingleTest instance = null;
private SingleTest(){
}
public SingleTest getInstance(){
if(null == instance)
synchronized (SingleTest.class) {
if(null == instance) instance = new SingleTest();
}
return instance;
}
}
使用了static 锁进行同步。当有多个线程同时执行到if语句判断时(第一个if语句):线程A执行if判断 instace==null;CPU切换到线程B执行,线程B执行if判断 instance==null。但是只有一个线程能够获得 static 锁进入同步代码块,当第一个线程进入同步代码块后 new 了SingleTest对象,后面的进程再进入同步代码块时,进行if判断为假,就不会再创建第二个SingleTest对象了。
4,饿汉模式与线程安全的懒汉模式比较
①二者都是线程安全的。对于饿汉模式而言,它在JVM加载该类时就已经创建好SingleTest对象了,因此有多个线程调用getInstance()时始终只有一个SingleTest对象存在。
②不管需不需要SingleTest对象,只要一加载SingleTest.java类,就会创建SingleTest对象,比如:假设SingleTest类中还定义了其他静态方法,通过类名.静态方法名() 调用静态方法时,会创建SingleTest对象,尽管此时并不需要使用SingleTest的实例对象。
若创建SingleTest对象开销很大,则有性能问题。而对于懒汉模式而言,只有在需要SingleTest对象时,才会创建,因为它是通过调用getInstance方法,然后在该方法里面new的对象;而对于饿汉模式,SingleTest对象在加载时已经生成,getInstance()方法只是负责返回该对象。
5,其他的一些多线程问题
①static 锁 与 this 锁
静态同步方法与同步方法 使用的锁
静态同步方法使用的是static锁。调用静态同步方法相当于获得了一个以 类名.class 的锁,如下:
synchronized (SingleTest.class) {//static 锁 //processing.... }
同步方法使用的是this锁。调用同步方法相当于获得了一个当前对象的锁。因为对于方法而言,是通过 对象.方法名进行调用的,即该方法被调用时,一定是某个对象调用了它,同步方法就获得了该对象的锁,如下:
synchronized(this){ //processing }
②线程执行了Thread.sleep(long)方法时,不会释放它所占有的锁。(注意:没有不带参数的sleep()方法)
private Object lock = new Object(); public void run(){ while(true) { synchronized(lock){ //do some processing try{ Thread.sleep(100); }catch(InterruptedException e){ } //do another processing } } }当线程获得了 lock锁进行了一些处理,然后睡眠100ms。当它执行sleep(100)后,会放弃CPU,进入阻塞状态。但是,它不会释放占有的 lock 锁。只有当它睡眠100ms后,重新获得CPU,再执行完另一些处理退出syncronized代码块之后,才会释放 lock 锁。
多线程入门资料参考:JAVA 多线程编程深入详解--汪文君
相关文章推荐
- java对世界各个时区(TimeZone)的通用转换处理方法(转载)
- java-注解annotation
- java-模拟tomcat服务器
- java-用HttpURLConnection发送Http请求.
- java-WEB中的监听器Lisener
- Android IPC进程间通讯机制
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- Python3写爬虫(四)多线程实现数据爬取
- 介绍一款信息管理系统的开源框架---jeecg
- 聚类算法之kmeans算法java版本
- java实现 PageRank算法
- PropertyChangeListener简单理解
- c++11 + SDL2 + ffmpeg +OpenAL + java = Android播放器
- 插入排序
- 冒泡排序
- 堆排序
- 快速排序