北京大学两学一做网站,现在开天猫店需要多少钱,建设局网站作用,会刊彩页设计最近#xff0c;我正在编写log4j附加程序#xff0c;并希望在自定义附加程序创建过程中使用logger记录一些诊断详细信息#xff0c;但是log4j初始化仅在创建附加程序实例后才完成#xff0c;因此该阶段记录的消息将被忽略。 我感到需要在自定义附加程序中进行延迟初始化我正在编写log4j附加程序并希望在自定义附加程序创建过程中使用logger记录一些诊断详细信息但是log4j初始化仅在创建附加程序实例后才完成因此该阶段记录的消息将被忽略。 我感到需要在自定义附加程序中进行延迟初始化并开始研究选项。 在此博客中我将分享我尝试过的事情。 我想到的一件事是Singleton方法但是现在已知的事实是Singleton会导致测试问题并且无法扩展它因此混合并发和对象构造的方法并不是那么好。 如果需要单例那么最好使用依赖注入框架而不是破坏应用程序代码。 让我们回到延迟初始化/评估。 一些编程语言例如scala / swift等支持惰性因此不需要自定义代码即可执行此操作但是在Java空间中我们仍然必须编写线程安全的代码才能正确执行。 让我们看一下Java中的一些选项以及获得的性能类型。 –使用同步的蛮力 这是最简单效率最低的一种scala正在使用这种方法。 Scala一个可用 ScalaLazy.java public class SingleLockV implements LazyV {private CallableV codeBlock;private V value;public SingleLock(CallableV codeBlock) {this.codeBlock codeBlock;}Overridepublic synchronized V get() {if (value null) {setValue();}return value;}private void setValue() {try {value codeBlock.call();} catch (Exception e) {throw new RuntimeException(e);}}} –双锁 编写起来并不复杂并且具有良好的性能。 public class DoubleLockV implements LazyV {private CallableV codeBlock;private V value;private volatile boolean loaded;public DoubleLock(CallableV codeBlock) {this.codeBlock codeBlock;}Overridepublic V get() {if (!loaded) {synchronized (this) {if (!loaded) {setValue();loaded true;}}}return value;}private void setValue() {try {value codeBlock.call();} catch (Exception e) {throw new RuntimeException(e);}}} –使用未来任务 这种方法易于编写并具有良好的性能。 public class LazyFutureTaskV implements LazyV {private final FutureTaskV futureTask;public LazyFutureTask(CallableV codeBlock) {this.futureTask new FutureTask(codeBlock);}Overridepublic V get() {futureTask.run();return getValue();}private V getValue() {try {return futureTask.get();} catch (Exception e) {throw new RuntimeException(e);}}
} 双锁方法可提供最佳性能而蛮力则是最差的。 我使用不同数量的线程对100万次调用进行了快速基准测试。 单锁性能非常差让我们通过删除单锁来查看数字以了解“双锁和未来任务”的执行情况。 这些基准测试很快完成但是详细的基准测试数字应该接近。 可以在github上获得此博客文章的代码 翻译自: https://www.javacodegeeks.com/2016/08/lazy-evaluation.html