Functional Programming in Java venkat(14) Being Lazy
admin
2024-03-03 00:46:02
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(不会产生任何同步开销)

相关内容

热门资讯

“我真的撑不住了”,2000万... 5月14日、15日两天,知名搞笑博主“大连老湿王博文”,分别在微信公众号和小红书上发表长文,宣布断更...
原创 9... 邱 林 没有想到的是,日本对中东地区石油依赖度竟高达96%,其中,阿联酋占43%,沙特阿拉伯占39%...
华金策略:A股短期可能难大调整... 来源:市场资讯 来源:华金证券 投资要点 复盘历史,驱动TMT行情结束的核心因素是外部事件和政策偏空...
5月18日突然大跌,金价行情拐... 刚刷完5月18日凌晨的金价数据,伦敦金现直接暴跌113.8美元,报4537.83美元/盎司,单日跌幅...
深化资本与产业协同 打造AI智... 央广网北京5月18日消息(记者 郭彦伟)“这款熊猫医生AI机器人主要能帮助大家实现生命体征检测、AI...
实地调研深圳融资市场 细数贷款... 在当下经济发展节奏较快的深圳,各行各业的资金周转需求愈发普遍,从个体日常大额支出、家庭置业规划,到个...
上市公司交出近三年最好成绩单 ... 上市公司是经济高质量发展的重要微观基础,稳中向好的成绩单有力印证中国经济的强大韧性与活力。从上市公司...
接连吃罚单!这家券商债券业务“... 5月15日,国都证券及其债券从业人员收到了北京证监局发出的5份行政处罚。 罚单显示,因在公司债券承销...
原创 美... 特朗普本次的中国之行,其深远影响将直接牵动美国今年中期选举的最终走向,因此,他此番远渡重洋,无疑是怀...
AI高景气与盈利持续兑现 机构... 存储芯片指数日K线图   范雨露 制图 上周,全球主要股指普遍回调,A股市场同样冲高回落,创业板指创...
2026天津房交会暨“新房市集... 近日,2026天津房交会暨“新房市集”活动在津一·PARK正式启幕。此次房交会由天津市房地产市场服务...
原创 【... 各位朋友,最近是不是感觉金店门口的“今日金价”牌子,数字变得有点“刺眼”?没错,黄金它……真的跌了,...
原创 推... 俄罗斯财长安东·西卢安诺夫接受自家媒体采访,透露了两条重磅消息。 第一个:中俄双边贸易中,本币结算率...
兆易创新盘中涨停续创历史新高 ... 5月18日早盘,兆易创新盘中涨停,股价续创历史新高,报412.87元/股,成交金额超130亿元,A+...
原创 价... 过去三年价格战硝烟弥漫,汽车价格一降再降。 然而曾经杀得眼红的车企们,如今集体踩下刹车,汽车售价不降...
4月居民贷款大幅缩水近8000... 一边是楼市延续修复态势,“小阳春”行情持续演绎,重点城市二手房成交量大幅攀升;另一边是居民信贷数据的...
金价暴涨里的“套保”迷影,山东... 山东黄金冶炼业务。图源:企业官网 本报(chinatimes.net.cn)记者张蓓 黄指南 深圳报...
扬帆出海获佳绩!盐田区携手黄金... 2026年5月8日至10日 在马来西亚槟城举办的 “2026马来西亚黄金珠宝展销会”上 深圳市盐田区...
政策底与情绪顶:5月18日-2... 文/金透社 万捷 2026年5月第三周(5月11日-15日),A股市场走出了鲜明的分化格局。上证指数...
证监会重罚欺诈发行,广发证券被... 4.63亿元。 这是2026年5月,证监会对清越科技、元道通信两家公司欺诈发行、财务造假的罚款总额。...