java中的惰性线程安全单例实例化模式
懒惰的线程安全单例实例对于每个编码人员来说都有点不容易理解,所以我想在我们的企业框架中创建一个类来完成这项工作 你觉得怎么样?你看到它有什么不好的地方吗?Apache Commons中是否有类似的东西?我怎样才能做得更好 Supplier.javajava中的惰性线程安全单例实例化模式,java,thread-safety,singleton,instantiation,lazy-evaluation,Java,Thread Safety,Singleton,Instantiation,Lazy Evaluation,懒惰的线程安全单例实例对于每个编码人员来说都有点不容易理解,所以我想在我们的企业框架中创建一个类来完成这项工作 你觉得怎么样?你看到它有什么不好的地方吗?Apache Commons中是否有类似的东西?我怎样才能做得更好 Supplier.java public interface Supplier<T> { public T get(); } 公共接口供应商{ 公众不能得到(); } lazythreadsafetinstantiator.java public cla
public interface Supplier<T> {
public T get();
}
公共接口供应商{
公众不能得到();
}
lazythreadsafetinstantiator.java
public class LazyThreadSafeInstantiator<T> implements Supplier<T> {
private final Supplier<T> instanceSupplier;
private volatile T obj;
public LazyThreadSafeInstantiator(Supplier<T> instanceSupplier) {
this.instanceSupplier = instanceSupplier;
}
@Override
// http://en.wikipedia.org/wiki/Double-checked_locking
public T get() {
T result = obj; // Wikipedia: Note the usage of the local variable result which seems unnecessary. For some versions of the Java VM, it will make the code 25% faster and for others, it won't hurt.
if (result == null) {
synchronized(this) {
result = obj;
if (result == null) {
result = instanceSupplier.get();
obj = result;
}
}
}
return result;
}
}
public类lazythreadsafe实例化器实现供应商{
私人最终供应商实例供应商;
私人银行;
公共LazyThreadSafe实例化器(供应商实例供应商){
this.instanceSupplier=instanceSupplier;
}
@凌驾
// http://en.wikipedia.org/wiki/Double-checked_locking
公共部门得不到{
T result=obj;//Wikipedia:注意局部变量result的用法,这似乎是不必要的。对于某些版本的Java VM,它将使代码速度提高25%,而对于其他版本,它不会有任何影响。
如果(结果==null){
已同步(此){
结果=obj;
如果(结果==null){
结果=instanceSupplier.get();
obj=结果;
}
}
}
返回结果;
}
}
用法示例:
public class Singleton1 {
private static final Supplier<Singleton1> instanceHolder =
new LazyThreadSafeInstantiator<Singleton1>(new Supplier<Singleton1>() {
@Override
public Singleton1 get() {
return new Singleton1();
}
});
public Singleton1 instance() {
return instanceHolder.get();
}
private Singleton1() {
System.out.println("Singleton1 instantiated");
}
}
公共类单音1{
私人静态最终供应商实例持有者=
新LazyThreadSafe实例化器(新供应商(){
@凌驾
公共单音1 get(){
返回新的Singleton1();
}
});
公共单例1实例(){
返回instanceHolder.get();
}
私人单音1(){
System.out.println(“单例1实例化”);
}
}
感谢您,JIT编译器和多核/处理器系统上的双重检查锁定模式和volatile的使用不是因为Java内存模型和无序执行的可能性吗
更一般地说,对于一个基本上可以正确实现的非常简单的模式来说,单例框架似乎有点过分了。对于一个比问题中提出的版本更可读(我认为)的版本,可以参考Bill Pugh介绍的。考虑到Java 5内存模型,它不仅是线程安全的,而且singleton的初始化也是惰性的。在我看来过于工程化了 我真的看不出有助手类有什么帮助 首先,它使用了双重锁定的习惯用法,并且已经被一次又一次地证明是错误的 其次,如果您必须使用singleton,为什么不初始化静态final实例呢
public class Singleton1 {
private static final Singleton1 instanceHolder =
new Singletong1( );
public Singleton1 instance() {
return instanceHolder;
}
private Singleton1() {
System.out.println("Singleton1 instantiated");
}
}
这段代码是线程安全的,并且已经被证明是有效的
查看Vineet Reynolds的答案,了解何时需要在首次获取时初始化singleton实例。在许多情况下,我认为这种方法也是一种过分的手段
懒惰的线程安全单例
实例化有点不容易
理解每一个编码员
不,实际上非常非常简单:
public class Singleton{
private final static Singleton instance = new Singleton();
private Singleton(){ ... }
public static Singleton getInstance(){ return instance; }
}
更好的是,将其设置为枚举:
public enum Singleton{
INSTANCE;
private Singleton(){ ... }
}
它是线程安全的,并且是惰性的(初始化发生在类加载时,Java在第一次引用类之前不会加载类)
事实上,99%的时间你根本不需要延迟加载。在剩下的1%中,在0.9%中,上面提到的已经足够懒了
您是否运行了探查器,并确定您的应用程序符合0.01%的要求,在首次访问时确实需要延迟加载?我不这么认为。那你为什么要浪费时间来编造这些讨厌的Rube goldbergsque代码来解决一个不存在的问题呢?我同意其他的海报,并说这看起来确实有些过分,但我确实认为这是一个初级开发人员可能会犯的错误。我认为,由于构造singleton(如下所示)的供应商的行为在几乎所有情况下都是相同的,因此我会尝试将其作为默认行为放在
LazyThreadSafe实例化器中。每当您想要使用单例时,使用注释性内部类是非常混乱的
@Override
public Singleton1 get() {
return new Singleton1();
}
这可以通过提供一个重载构造函数来完成,该构造函数将类带到所需的单例
public class LazyThreadSafeInstantiator<T> implements Supplier<T> {
private final Supplier<T> instanceSupplier;
private Class<T> toConstruct;
private volatile T obj;
public LazyThreadSafeInstantiator(Supplier<T> instanceSupplier) {
this.instanceSupplier = instanceSupplier;
}
public LazyThreadSafeInstantiator(Class<t> toConstruct) {
this.toConstruct = toConstruct;
}
@Override
// http://en.wikipedia.org/wiki/Double-checked_locking
public T get() {
T result = obj; // Wikipedia: Note the usage of the local variable result which seems unnecessary. For some versions of the Java VM, it will make the code 25% faster and for others, it won't hurt.
if (result == null) {
synchronized(this) {
result = obj;
if (result == null) {
if (instanceSupplier == null) {
try {
Constructor[] c = toConstruct.getDeclaredConstructors();
c[0].setAccessible(true);
result = c[0].newInstance(new Object[] {});
} catch (Exception e) {
//handle
}
result =
} else {
result = instanceSupplier.get();
}
obj = result;
}
}
}
return result;
}
}
public类lazythreadsafe实例化器实现供应商{
私人最终供应商实例供应商;
私人建筑类;
私人银行;
公共LazyThreadSafe实例化器(供应商实例供应商){
this.instanceSupplier=instanceSupplier;
}
公共LazyThreadSafe实例化器(类toConstruct){
this.toConstruct=toConstruct;
}
@凌驾
// http://en.wikipedia.org/wiki/Double-checked_locking
公共部门得不到{
T result=obj;//Wikipedia:注意局部变量result的用法,这似乎是不必要的。对于某些版本的Java VM,它将使代码速度提高25%,而对于其他版本,它不会有任何影响。
如果(结果==null){
已同步(此){
结果=obj;
如果(结果==null){
如果(instanceSupplier==null){
试一试{
构造函数[]c=toConstruct.getDeclaredConstructors();
c[0].setAccessible(true);
结果=c[0].newInstance(新对象[]{});
}捕获(例外e){
//处理
}
结果=
}否则{
结果=instanceSupplier.get();
}
obj=结果;
}
}
}
返回结果;
}
}
这样就可以这样使用了
private static final Supplier<Singleton1> instanceHolder =
new LazyThreadSafeInstantiator<Singleton1>(Singleton1.getClass());
私有静态最终供应商实例持有者=
新的LazyThreadSafe实例化器(Singleton1.getC
Lazy<X> lazyX= new Lazy<X>(){
protected X create(){
return new X();
}};
X x = lazyX.get();
abstract public class Lazy<T>
{
abstract protected T create();
static class FinalRef<S>
{
final S value;
FinalRef(S value){ this.value =value; }
}
FinalRef<T> ref = null;
public T get()
{
FinalRef<T> result = ref;
if(result==null)
{
synchronized(this)
{
if(ref==null)
ref = new FinalRef<T>( create() );
result = ref;
}
}
return result.value;
}
}