日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

你研究过单例么?这样写单例效率最高.

發(fā)布時(shí)間:2023/12/10 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 你研究过单例么?这样写单例效率最高. 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

首先,小湯我在這里,要表示一下歉意,本來是想要每天寫一篇Swift的學(xué)習(xí)小tip的,無奈近期手頭的money花差的差點(diǎn)兒相同了,僅僅能迫不得已,出門找工作去了,沒能履行承諾之處還請(qǐng)大家見諒.

那么,廢話不多說了,開始我們今天的主題: 單例 !

單例介紹:

說到單例,大家應(yīng)該都不陌生,在傳說中的那23種 (為啥我就會(huì)6種捏o(╯□╰)o…) 設(shè)計(jì)模式中,單例應(yīng)該是屬于和簡(jiǎn)單工廠模式并列的最簡(jiǎn)單的設(shè)計(jì)模式了,也應(yīng)該是最經(jīng)常使用的.

像這樣簡(jiǎn)單易懂,又能有效提高程序執(zhí)行效率的設(shè)計(jì)模式,作為一個(gè)iOS程序猿,必定是十分熟練的啦.

今天啊,小湯我就給大家介紹一下在Objective-C中,我們經(jīng)常使用的單例模式的寫法,以及小湯我在研究當(dāng)中某種寫法時(shí),寫出來的一個(gè)效率更高的寫法.

當(dāng)然啦,MRC下的寫法,我就不多說了,已經(jīng)有那么多大牛寫過了,我就簡(jiǎn)化一下,直接寫在ARC下的寫法啦,MRC能夠直接把相關(guān)代碼套用過去即可嘍~

網(wǎng)上流傳的Objective-C的單例寫法:

+ (instancetype)sharedPerson0{static id instance0 = nil;static BOOL once0 = YES;@synchronized(self){if (once0) {instance0 = [[Person alloc]init];once0 = NO;}}return instance0;} 以上就是網(wǎng)上流傳已久的單例模式的寫法啦.

通過GCD實(shí)現(xiàn)的單例模式寫法:

+ (instancetype)sharedPerson1{static id instance1 = nil;static dispatch_once_t onceToken;dispatch_once(&onceToken, ^{instance1 = [[self alloc]init];});return instance1;} 這是GCD方式,也就是使用dispatch_once實(shí)現(xiàn)的單例模式的寫法.

首先展示一下兩者是不是都實(shí)現(xiàn)了單例呢?為此,小湯我新建了一個(gè)Person類,在當(dāng)中實(shí)現(xiàn)了這兩種方法,然后在控制器啟動(dòng)的時(shí)候執(zhí)行了以下兩段代碼

for (int i = 0; i < 10; i++) {NSLog(@"--單例方法0:%@",[Person sharedPerson0]);}NSLog(@"-----");for (int i = 0; i < 10; i++) {NSLog(@"--單例方法1:%@",[Person sharedPerson1]);}NSLog(@"-----");

執(zhí)行結(jié)果例如以下:

2015-06-06 14:46:35.906 test[966:22855] --單例方法0:<Person: 0x7f9c19418740>2015-06-06 14:46:35.907 test[966:22855] --單例方法0:<Person: 0x7f9c19418740>2015-06-06 14:46:35.907 test[966:22855] --單例方法0:<Person: 0x7f9c19418740>2015-06-06 14:46:35.907 test[966:22855] --單例方法0:<Person: 0x7f9c19418740>2015-06-06 14:46:35.907 test[966:22855] --單例方法0:<Person: 0x7f9c19418740>2015-06-06 14:46:35.907 test[966:22855] --單例方法0:<Person: 0x7f9c19418740>2015-06-06 14:46:35.907 test[966:22855] --單例方法0:<Person: 0x7f9c19418740>2015-06-06 14:46:35.907 test[966:22855] --單例方法0:<Person: 0x7f9c19418740>2015-06-06 14:46:35.907 test[966:22855] --單例方法0:<Person: 0x7f9c19418740>2015-06-06 14:46:35.908 test[966:22855] --單例方法0:<Person: 0x7f9c19418740>2015-06-06 14:46:35.908 test[966:22855] -----2015-06-06 14:46:35.908 test[966:22855] --單例方法1:<Person: 0x7f9c1961e510>2015-06-06 14:46:35.908 test[966:22855] --單例方法1:<Person: 0x7f9c1961e510>2015-06-06 14:46:35.908 test[966:22855] --單例方法1:<Person: 0x7f9c1961e510>2015-06-06 14:46:35.908 test[966:22855] --單例方法1:<Person: 0x7f9c1961e510>2015-06-06 14:46:35.908 test[966:22855] --單例方法1:<Person: 0x7f9c1961e510>2015-06-06 14:46:35.908 test[966:22855] --單例方法1:<Person: 0x7f9c1961e510>2015-06-06 14:46:35.960 test[966:22855] --單例方法1:<Person: 0x7f9c1961e510>2015-06-06 14:46:35.960 test[966:22855] --單例方法1:<Person: 0x7f9c1961e510>2015-06-06 14:46:35.960 test[966:22855] --單例方法1:<Person: 0x7f9c1961e510>2015-06-06 14:46:35.960 test[966:22855] --單例方法1:<Person: 0x7f9c1961e510>2015-06-06 14:46:35.960 test[966:22855] -----

能夠看到這兩種方式寫的單例模式都是能夠?qū)崿F(xiàn)我們的需求的.
那么兩者有什么差別呢?
以下我們來看一看兩者在執(zhí)行時(shí)間上的差別:

CFAbsoluteTime start = CFAbsoluteTimeGetCurrent();for (int i = 0; i < 1000000; ++i) {[Person sharedPerson0];}NSLog(@"====方法0耗時(shí):%f",CFAbsoluteTimeGetCurrent() - start);start = CFAbsoluteTimeGetCurrent();for (int i = 0; i < 1000000; ++i) {[Person sharedPerson1];}NSLog(@"====方法1耗時(shí):%f",CFAbsoluteTimeGetCurrent() - start);

我通過上面這兩個(gè)方法,比較兩個(gè)單例模式在分別實(shí)例化100萬個(gè)對(duì)象的耗時(shí),結(jié)果例如以下:

2015-06-06 14:50:47.899 test[1009:24267] ====方法0耗時(shí):0.1842172015-06-06 14:50:47.981 test[1009:24267] ====方法1耗時(shí):0.081377

能夠看到,方法1的耗時(shí)明顯要少于方法二的耗時(shí),那么為什么GCD能夠做到這一點(diǎn)呢?
小湯思考之后,認(rèn)為應(yīng)該是@synchronized這個(gè)鎖對(duì)性能的消耗十分明顯.

而在打印了dispatch_once這種方法的入?yún)nceToken之后,發(fā)現(xiàn),在實(shí)例化這個(gè)對(duì)象之前,onceToken的值為0,而之后變?yōu)?1.

于是,在這個(gè)基礎(chǔ)上,小湯我想到了一個(gè)方法來降低這樣的性能消耗.

那么問題來了?

dispatch_once會(huì)是通過小湯我想象的這樣做的么?

小湯我的單例實(shí)現(xiàn):

+ (instancetype)sharedPerson2{static id instance2 = nil;static BOOL once2 = YES;static BOOL isAlloc = NO;if (!isAlloc) {@synchronized(self){if (once2) {instance2 = [[Person alloc]init];once2 = NO;isAlloc = YES;}}}return instance2;}

我在進(jìn)行同步鎖之前,再進(jìn)行了一次推斷,這樣會(huì)導(dǎo)致什么后果呢?


非常顯然,因?yàn)閮?nèi)部有相互排斥鎖,那么在實(shí)例化對(duì)象時(shí),肯定僅僅有一個(gè)對(duì)象被實(shí)例化,然后在實(shí)例化對(duì)象之后,因?yàn)閮?nèi)部存在一個(gè)推斷,那么就不會(huì)再有其它的對(duì)象被實(shí)例化,而在外面的這個(gè)推斷,又能在下一次外部變量進(jìn)行訪問的時(shí)候直接返回值,提高了效率.

說了那么多,先來測(cè)試一下小湯我的代碼是不是能夠創(chuàng)建一個(gè)單例呢?


測(cè)試代碼:

for (int i = 0; i < 10; i++) {NSLog(@"--單例方法2:%@",[Person sharedPerson2]);}NSLog(@"-----");

測(cè)試結(jié)果:

2015-06-06 15:01:40.412 test[1081:26913] --單例方法2:<Person: 0x7fd891553e20>2015-06-06 15:01:40.412 test[1081:26913] --單例方法2:<Person: 0x7fd891553e20>2015-06-06 15:01:40.412 test[1081:26913] --單例方法2:<Person: 0x7fd891553e20>2015-06-06 15:01:40.412 test[1081:26913] --單例方法2:<Person: 0x7fd891553e20>2015-06-06 15:01:40.412 test[1081:26913] --單例方法2:<Person: 0x7fd891553e20>2015-06-06 15:01:40.413 test[1081:26913] --單例方法2:<Person: 0x7fd891553e20>2015-06-06 15:01:40.413 test[1081:26913] --單例方法2:<Person: 0x7fd891553e20>2015-06-06 15:01:40.413 test[1081:26913] --單例方法2:<Person: 0x7fd891553e20>2015-06-06 15:01:40.413 test[1081:26913] --單例方法2:<Person: 0x7fd891553e20>2015-06-06 15:01:40.413 test[1081:26913] --單例方法2:<Person: 0x7fd891553e20>2015-06-06 15:01:40.413 test[1081:26913] -----

以上結(jié)果能夠顯示,小湯我的單例也是可行的.那么我們來對(duì)照一下我的這個(gè)實(shí)現(xiàn)和GCD的那種實(shí)現(xiàn)方式是不是一樣呢?


效率測(cè)試代碼:

CFAbsoluteTime start = CFAbsoluteTimeGetCurrent();for (int i = 0; i < 1000000; ++i) {[Person sharedPerson1];}NSLog(@"====方法1耗時(shí):%f",CFAbsoluteTimeGetCurrent() - start);start = CFAbsoluteTimeGetCurrent();for (int i = 0; i < 1000000; ++i) {[Person sharedPerson2];}NSLog(@"====方法2耗時(shí):%f",CFAbsoluteTimeGetCurrent() - start);

還是比較100萬次,我們來看看效率怎樣呢?
測(cè)試結(jié)果:

2015-06-06 15:04:58.696 test[1125:28301] ====方法1耗時(shí):0.0897542015-06-06 15:04:58.763 test[1125:28301] ====方法2耗時(shí):0.065470

結(jié)果是不是非常驚訝?! 我 也 表 示 非常 吃 驚 !
沒有想到小湯我寫的單例的效率竟然比dispatch_once的效率還要略高那么一絲.
當(dāng)然,這個(gè)僅僅是讓小湯我稍微嘚瑟了一下,重點(diǎn)是,小湯我還是沒想清楚,GCD下的這個(gè)dispatch_once究竟是怎么實(shí)現(xiàn)的呢?


是不是還存在優(yōu)化的可能呢?希望對(duì)此有研究的各位大牛給個(gè)答案哈~

總結(jié)

以上是生活随笔為你收集整理的你研究过单例么?这样写单例效率最高.的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。