Functional Programming in Java venkat(14) Being Lazy
admin
2024-04-15 01:07:17
0

文章目录

  • Functional Programming in Java venkat(14): Being Lazy
    • Delayed Initialization
      • A Familiar Approach
      • Providing Thread Safety
      • Adding a Level of Indirection
    • 英文

Functional Programming in Java venkat(14): Being Lazy

这里是记录学习这本书 Functional Programming in Java: Harnessing the Power Of Java 8 Lambda Expressions 的读书笔记,如有侵权,请联系删除。

本章的内容:延时创建heavyweight 的对象,然后把eager的计算的情形转变为lazy评估。

In this chapter we start with a task to postpone the creation of a heavyweight object, then we turn some eager computations into lazy evaluations.

Delayed Initialization

eager is easy to write and to reason about. But delaying commitments until the last responsible moment is a good agile practice.

A Familiar Approach

把heavyweight的资源放在Heavy类中。

move the heavyweight resources into another class—say, Heavy. Then an instance of Holder will keep a reference to an instance of Heavy and route calls to it as appropriate.

package fpij;public class Heavy {public Heavy() { System.out.println("Heavy created"); }public String toString() { return "quite heavy"; }
}

下面是最简单的延迟创建Heavy对象,当heavy = null 的时候创建新的Heavy对象,否则的话返回heavy对象。

package fpij;public class HolderNaive {private Heavy heavy;public HolderNaive() {System.out.println("Holder created");}public Heavy getHeavy() {if(heavy == null) {heavy = new Heavy();}return heavy;}//...public static void main(final String[] args) {final HolderNaive holder = new HolderNaive();System.out.println("deferring heavy creation...");System.out.println(holder.getHeavy());System.out.println(holder.getHeavy());}
}

但是存在问题:线程不安全

如果多个线程同时进来,可能会创建多个heavy对象。

That appears to work. The solution, however, is not simple; it is a familiar
but also a rather simplistic solution that fails thread safety. Let’s work through
it.

Providing Thread Safety

变成线程安全的需要synchronized关键字

  public synchronized Heavy getHeavy() {if(heavy == null) {heavy = new Heavy();}return heavy;}

多个线程进来,满足互斥。只有一个可以进入创建对象,其他的线程进入之后会发现对象已经被之前的线程创建,从而直接返回heavy对象。

If two or more threads call this method concurrently, due to mutual exclusion only one will be allowed to enter and the others will queue up for their turn. The first one to enter into the method will create the instance. When subsequent threads enter this method they will see that the instance already exists,
and will simply return it.

我们避免了竞赛条件,但这个解决方案产生了另一个负面影响。现在对getHeavy()方法的每一次调用都必须忍受同步开销;即使没有同时竞争的线程,调用线程也必须跨越内存障碍(memory barrier)。

We averted the race condition, but the solution created another negative impact. Every call to the getHeavy() method now has to endure the synchronization overhead; the calling threads have to cross the memory barrier even if there are no concurrently competing threads.

Adding a Level of Indirection


import java.util.function.Supplier;public class Holder {private Supplier heavy = () -> createAndCacheHeavy();public Holder() {System.out.println("Holder created");}public Heavy getHeavy() {return heavy.get();}//...
}

当Holder的实例被创建时,我们可以看到,Heavy的实例并没有被创建。这种设计实现了懒惰初始化的目标。我们还需要一个非苛刻的线程安全解决方案。这就是createAndCacheHeavy()方法的用处。

When an instance of Holder is created, as we can see, an instance of Heavy is not created. This design achieves the goal of lazy initialization. We also need a non-draconian solution to thread safety. This is where the createAndCacheHeavy() method comes in.

查看createAndCacheHeavy方法

 private synchronized Heavy createAndCacheHeavy() {class HeavyFactory implements Supplier {private final Heavy heavyInstance = new Heavy();public Heavy get() { return heavyInstance; }}if(!HeavyFactory.class.isInstance(heavy)) {heavy = new HeavyFactory();}return heavy.get();}

让我们考虑这样一个场景:一个新的Holder实例刚刚被创建。我们假设有两个线程同时调用getHeavy()方法,随后第三个线程在很久之后调用这个方法。当前两个线程在Holder中调用默认Supplier的get()方法时,createAndCacheHeavy()方法会让其中一个线程通过,让另一个线程等待。第一个进入的线程将检查heavy是否是HeavyFactory的一个实例。由于它不是默认的Supplier,这个线程将用HeavyFactory的一个实例来替换heavy。最后它返回这个HeavyFactory所持有的Heavy实例。

Let’s consider a scenario in which a new instance of Holder has just been created. Let’s assume two threads invoke the getHeavy() method concurrently, followed by a third thread calling this method much later. When the first two threads call the default supplier’s get() method in the Holder, the createAndCacheHeavy() method will let one of them through and make the other wait. The first thread to enter will check if heavy is an instance of the HeavyFactory. Since it is not the default Supplier, this thread will replace heavy with an instance of HeavyFactory. Finally it returns the Heavy instance that this HeavyFactory holds.

现在heavy已经被HeavyFactory所取代,随后对getHeavy()方法的调用将直接进入HeavyFactory的get()方法,不会产生任何同步开销。

Now that heavy has been replaced with HeavyFactory, subsequent calls to the getHeavy() method will go directly to the HeavyFactory’s get() method and will not incur any synchronization overhead

我们设计了懒惰的初始化,同时,避免了空值检查。此外,我们确保了懒惰实例创建的线程安全。这是虚拟代理模式的一个简单、轻量级的实现。接下来我们将使用lambda表达式来延缓函数的评估。

We designed lazy initialization and, at the same time, avoided null checks. Furthermore, we ensured the thread safety of the lazy instance creation. This is a simple, lightweight implementation of the virtual proxy pattern. Next we’ll use lambda expressions to postpone function evaluations.

英文

overhead: 开销

will not incur any synchronization overhead(不会产生任何同步开销)

相关内容

热门资讯

东方贡茶回应“拖鞋放进珍珠奶茶... 针对近日发生的“拖鞋放进珍珠奶茶”事件,东方贡茶作出回应。9月18日,东方贡茶在社交平台发布声明称,...
关于江西菜的10个冷知识,如江... 关于江西菜的十条冷知识,带你从瓦罐汤的醇厚到南昌米酒的甜香,感受这片土地独特的饮食文化。 1. 瓦...
关于中国菜系的10个冷知识,如... 关于中国菜系的十个冷知识,经过重新组织与改写,保留核心信息并提升原创性: 1. 广东菜以新鲜清爽和原...
成都担担面:麻辣里的市井温情 成都宽窄巷子深处,“陈婆婆担担面”的铺面不大,却总能听到熟悉的吆喝声。八十岁的陈婆婆虽已不亲自挑担叫...
关于中国菜系,你不知道的10个... 关于中国菜系你可能不知道的十条冷知识 1. 粤菜以清鲜淡雅著称,讲究保留食材的原汁原味,代表性菜肴如...
重要提示!事关中秋、国庆出游 ... 9月18日,在国庆、中秋假期即将来临之际,云南省文化和旅游厅提醒广大游客合理规划行程,畅享无忧出行。...
连吃一个月,气血养回来了!4碗... 1、猪肘红烧鲍鱼! 2、金针花菜炖排骨汤! 3、鲜蘑菇炒鸡蛋! 4、枸杞桂花藕...
夜读|每代人都有自己的“丝瓜汤... 第一次从短视频里看到“丝光汤”这个梗时,我顿了一下,继而哑然失笑。因为当时我正在厨房里切丝瓜,旁边的...
湘菜大师丁建国喜收八徒,共续湖... 仪式现场庄重热烈,众星云集共襄盛举 9月17日下午,中国注册烹饪大师、湘菜大师丁建国收徒仪式,在长沙...
【紫牛头条】重庆姑娘比利时摆摊... 在比利时的市集上,一碗改良版重庆豌杂面正散发着独特香气——来自异国他乡的食客捧着热腾腾的面,小心翼翼...
去一次四川要花多少钱,去成都旅... 宝子们,四川,这片位于祖国西南的神奇土地,宛如一颗璀璨的明珠,散发着独特而迷人的光彩。它有着“天府之...
空间酒店国庆房价从90元涨至1... 图片来源:视觉中国 蓝鲸新闻9月18日讯(记者 孙煜)十一假期将至,酒店预订也迎来了一波热潮。 近日...
周末到河北,你不能错过的城市—... 长城网·冀云客户端讯(记者 魏亚慧 郭硕 通讯员 陆倩)9月16日晚,河北省第九届旅游产业发展大会举...
报告显示中国—东盟人民币跨境收... 中新社南宁9月18日电 (记者 黄艳梅)2025中国—东盟金融合作与发展论坛18日在广西南宁市举办,...
新疆大环线私人订制15天游价格... 新疆大环线私人订制15天游人均总费用4500元,乌鲁木齐九月秋意正浓,是体验新疆壮美风光的绝佳时节。...
户外人速码这份指南!下一站:四... 封面新闻记者 谢杰当城市的霓虹晃花眼,当写字楼的空调吹僵身体,越来越多人把脚步迈向山野——户外徒步。...
【河源一桌菜】龙川长诚酒家:匠... 在“河源一桌菜”评选活动中,龙川长诚酒家凭借招牌菜品“龙川八宝鱼生”脱颖而出,成功入选。这道承载着龙...