首先了解一下Singleton模式通常的两种表现形式:
第一种形式:
public
class
Singleton {
private
Singleton(){}
//
在自己内部定义自己一个实例,是不是很奇怪?
//
注意这是private 只供内部调用
private
static
Singleton instance
=
new
Singleton();
//
这里提供了一个供外部访问本class的静态方法,可以直接访问
public
static
Singleton getInstance() {
return
instance;
}
}
第二种形式:
public
class
Singleton {
private
static
Singleton instance
=
null
;
public
static
synchronized
Singleton getInstance() {
//
这个方法比上面有所改进,不用每次都进行生成对象,只是第一次
//
使用时生成实例,提高了效率!
if
(instance
==
null
) instance=
new
Singleton();
return
instance;
}
}
使用Singleton.getInstance()可以访问单态类。
上面第二中形式就是lazy initialization,也就是说第一次调用时初始Singleton,以后就不用再生成了。
注意到lazy initialization形式中的synchronized,这个synchronized很重要,如果没有synchronized,那么使用getInstance()是有可能得到多个Singleton实例。
那么为什么只有使用synchronized关键字才可以达到单态的目的呢?synchronized到底有什么含义呢?
synchronized 关键字,它包括两种用法:synchronized 方法和 synchronized 块。
1.
synchronized 方法
:通过在方法声明中加入 synchronized关键字来声明 synchronized 方法。如:
public
synchronized
void
accessVal(
int
newVal);
synchronized 方法控制对类成员变量的访问:每个类实例对应一把锁,每个 synchronized 方法都必须获得调用该方法的类实例的锁方能执行,否则所属线程阻塞,方法一旦执行,就独占该锁,直到从该方法返回时才将锁释放,此后被阻塞的线程方能获得该锁,重新进入可执行状态。
这
种机制确保了同一时刻对于每一个类实例,其所有声明为 synchronized
的成员函数中至多只有一个处于可执行状态(因为至多只有一个能够获得该类实例对应的锁),从而有效避免了类成员变量的访问冲突(只要所有可能访问类成员变
量的方法均被声明为 synchronized)。
在 Java 中,不光是类实例,每一个类也对应一把锁,这样我们也可将类的静态成员函数声明为 synchronized ,以控制其对类的静态成员变量的访问。
synchronized
方法的缺陷:若将一个大的方法声明为synchronized 将会大大影响效率,典型地,若将线程类的方法 run() 声明为
synchronized ,由于在线程的整个生命期内它一直在运行,因此将导致它对本类任何 synchronized
方法的调用都永远不会成功。当然我们可以通过将访问类成员变量的代码放到专门的方法中,将其声明为 synchronized
,并在主方法中调用来解决这一问题,但是 Java 为我们提供了更好的解决办法,那就是 synchronized 块。
2. synchronized 块
:通过 synchronized关键字来声明synchronized 块。语法如下:
synchronized
(syncObject) {
//
允许访问控制的代码
}
synchronized 块是这样一个代码块,其中的代码必须获得对象 syncObject (如前所述,可以是类实例或类)的锁方能执行,具体机制同前所述。由于可以针对任意代码块,且可任意指定上锁的对象,故灵活性较高。
对synchronized(this)的一些理解
一、当两个并发线程访问同一个对象object中的这个synchronized(this)同步代码块时,一个时间内只能有一个线程得到执行。另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块。
二、然而,当一个线程访问object的一个synchronized(this)同步代码块时,另一个线程仍然可以访问该object中的非synchronized(this)同步代码块。
三、尤其关键的是,当一个线程访问object的一个synchronized(this)同步代码块时,其他线程对object中所有其它synchronized(this)同步代码块的访问将被阻塞。
四、第三个例子同样适用其它同步代码块。也就是说,当一个线程访问object的一个synchronized(this)同步代码块时,它就获得了这个object的对象锁。结果,其它线程对该object对象所有同步代码部分的访问都被暂时阻塞。
五、以上规则对其它对象锁同样适用
分享到:
相关推荐
js lazyload实现网页图片延迟加载特效
jquery.lazyload 实现图片延迟加载,ImageLazyLoad技术就是,当前可见界面的图片是加载进来的,而不可见页面
lazyload.js实现图片异步延迟加载
一个组件实现lazyload图片当在视窗内(或附近)时才加载
lazy binomial heaps的oython实现,优先队列。采用双向循环链表实现,api:merge,insert,find_min,extractMin,coalesce_step,updateMin。
Lazy
本文介绍了浅谈vue-lazyload实现的详细过程,分享给大家,也给自己留个笔记 首先 ,在命令行输入npm install vue-lazyload&&cnpm install vue-lazyload 然后,在main.js里引入这个模块。 import 'VueLazyload' from ...
Lazyload是通过延迟加载来实现按需加载,达到节省资源,加快浏览速度的目的。 网上也有不少类似的效果,这个Lazyload主要特点是: 支持使用window(窗口)或元素作为容器对象; 对静态(位置大小不变)元素做了大量...
在https://github.com/gramoli/synchrobench上进行修改更适于Synchrobench’s Lazy Linked-List进行内存回收,解决了内存泄漏问题
JQuery LazyLoad 图片懒加载实例,相关描述可查看我的博文“JQuery.LazyLoad 实现图片懒加载”
Lazy_Theta_star是在 Theta_star上的进一步改进,Theta_star是当节点加入open表时和当前点的父节点进行比较g值是否更小,对一些不必要的节点计算浪费了时间,而Lazy_Theta_star则是在弹出open表后进行比较,减少了...
jQuery_lazyload插件示例Demo
lazyload.js可以实现图片分批次加载,不是一次性加载完毕再分批次展现。使用该插件有个注意的地方,图片要加上宽高。因为默认图是1像素的,所以如果没有给图片限制宽高,当滚动条滚动时会全部加载出来。
懒加载案例 lazyload 自己做了一个懒加载的案例,供大家参考
lazyload, JavaScript, 图片懒加载, h5
Lazy Load 是一个用 JavaScript 编写的 jQuery 插件. 它可以延迟加载长页面中的图片. 在浏览器可视区域外的图片不会被载入, 直到用户将页面滚动到它们所在的位置. 这与图片预加载的处理方式正好是相反的. 在包含很多...
图片懒加载lazyload,增快页面访问速度。
用于显示动态加载的图片如何通过JQuery.LazyLoad控件实现延迟加载,可惜目前例子在谷歌浏览器下还有些问题
Lazy Load Plugin for jQuery
没解决方案,就得发挥咱DIY的精神,自己想法解决,分析了BUG,理了理思路,结合前段时间我做弹出窗口特效的方法,解决了Jquery.LazyLoad.js的兼容问题,现将思路和方法与大家分享一下。 解决思路大致是两点,一是...