NSThread使用&GCD使用&&NSOperation使用&&線程安全

純屬娛樂

0.0 簡(jiǎn)介

(1) 進(jìn)程和線程基本概念【查看活動(dòng)監(jiān)視器】

> 什么是進(jìn)程

a昧辽、是指在系統(tǒng)中正在運(yùn)行的一個(gè)應(yīng)用程序冠王;

b向挖、每個(gè)進(jìn)程之間是獨(dú)立的,每個(gè)進(jìn)程運(yùn)行在其專用且受保護(hù)的內(nèi)存空間哪替;

> 什么是線程

a栋荸、一個(gè)進(jìn)程想要執(zhí)行任務(wù),必須得有線程(每個(gè)進(jìn)程至少要有一條線程)凭舶;

b晌块、線程是進(jìn)程的基本執(zhí)行單元,一個(gè)進(jìn)程(程序)的所有任務(wù)都在線程中執(zhí)行帅霜;

> 線程的串行

a匆背、一個(gè)線程中任務(wù)的執(zhí)行是串行的(在一個(gè)線程中執(zhí)行多個(gè)任務(wù),那么只能一個(gè)一個(gè)的按順序執(zhí)行身冀,在同一時(shí)間內(nèi)钝尸,一個(gè)線程只能執(zhí)行一個(gè)任務(wù));

> 線程的并行

a搂根、一個(gè)進(jìn)程中可以開啟多條線程珍促,每條線程可以并行(同時(shí))執(zhí)行不同的任務(wù);

【例如在一個(gè)線程中下載3個(gè)文件是串行剩愧;同時(shí)開啟3條線程分別下載3個(gè)文件是并行】

> 多線程的原理

a猪叙、單核CPU:同一時(shí)間,CPU只能處理一條線程仁卷,只有一條線程在工作(執(zhí)行)穴翩;多線程并發(fā)(同時(shí))執(zhí)行,其實(shí)是CPU快速的在多條線程之間調(diào)度(切換/輪詢)锦积;CPU調(diào)度線程的時(shí)間足夠快藏否,看到的多線程并發(fā)(同時(shí))執(zhí)行的假象;

b充包、多核CPU

> 多線程優(yōu)缺點(diǎn)

a、優(yōu)點(diǎn):適當(dāng)提高程序的執(zhí)行效率;適當(dāng)提高資源利用率(CPU/內(nèi)存利用率)基矮;

b淆储、缺點(diǎn):開啟線程需要占用一定的內(nèi)存空間(默認(rèn)情況下,主線程占用1M家浇,子線程占用512KB)本砰,如果開啟大量的線程,會(huì)占用大量的內(nèi)存空間钢悲,降低程序的性能点额;

> iOS創(chuàng)建線程的方式

pthread/NSThread/GCD/NSOperation

pthread用法

IPHONE4: 512m

安卓: 2G

安卓(多進(jìn)程): Linux + JAVA虛擬機(jī) + 應(yīng)用程序

(QQ100M + 微信100M + UC瀏覽器100M + 游戲500M + 系統(tǒng)1G)

蘋果(多任務(wù)): 512M只有一個(gè)人用

1,NSThread

a,顯示創(chuàng)建alloc init會(huì)創(chuàng)建新的線程,需要手動(dòng)開啟start莺琳,線程可以設(shè)置名字name还棱。方法運(yùn)行結(jié)束,線程結(jié)束惭等。

2,b,隱式創(chuàng)建新線程珍手,自動(dòng)開啟

3,YES&&NO

1,YES即等待線程@selector操作做完才繼續(xù)執(zhí)行

2,NO即不等待線程線程操作完成

此圖請(qǐng)自動(dòng)忽略水印

4,線程的生命周期:

? ? ? ? ? ? ?1,alloc+init:即創(chuàng)建對(duì)象,在運(yùn)行的內(nèi)存中辞做;

? ? ? ? ? ? 2,start:即線程為就緒態(tài) (萬事具備琳要,等待CPU);

? ? ? ? ? ? 3,當(dāng)CPU調(diào)度當(dāng)前線程:即線程為運(yùn)行態(tài)秤茅;

? ? ? ? ? ? 4當(dāng)CPU調(diào)度其他線程:即線程又回到就緒態(tài)稚补;

? ? ? ? ? ? 5,當(dāng)線程調(diào)用了sleep、等待同步鎖:即線程為阻塞態(tài)框喳;

? ? ? ? ? ? 6,當(dāng)線程中sleep完课幕、得到同步鎖:即線程變?yōu)榫途w態(tài);

? ? ? ? ? ? ?7,當(dāng)線程任務(wù)執(zhí)行完成/異常/強(qiáng)制退出:即線程為死亡態(tài)帖努;

5,線程安全 沒有加鎖撰豺,訪問的數(shù)據(jù)不是想要的

6,線程安全 沒有加鎖,訪問的數(shù)據(jù)不是想要的

7,線程安全 使用@synchronized加鎖拼余,訪問的數(shù)據(jù)是想要的

8,線程安全 使用NSLock加鎖污桦,訪問的數(shù)據(jù)是想要的

9,GCD簡(jiǎn)介

> 什么是GCD

a、全稱是Grand Center Dispatch匙监,即中樞調(diào)度器凡橱;

b、純C語(yǔ)言亭姥,提供了非常多強(qiáng)大的函數(shù)稼钩;

> GCD的優(yōu)勢(shì)

a、GCD是蘋果公司為多核的并行運(yùn)算提出的解決方案达罗;

b坝撑、GCD會(huì)自動(dòng)利用更多的CPU內(nèi)核(比如雙核静秆、四核);

c巡李、GCD會(huì)自動(dòng)管理線程的生命周期(創(chuàng)建線程抚笔、調(diào)度任務(wù)、銷毀線程)侨拦;

d殊橙、程序員只需要告訴GCD想要執(zhí)行什么任務(wù),不需要編寫任何線程管理代碼狱从;

> GCD的2個(gè)核心概念

a膨蛮、任務(wù):執(zhí)行什么操作(執(zhí)行下載、播放音樂等)季研;

b敞葛、隊(duì)列:用來存放任務(wù);

> GCD的使用步驟

a训貌、定制任務(wù)[確定想要做的事情]制肮;

b、將任務(wù)添加到隊(duì)列中[GCD會(huì)自動(dòng)將隊(duì)列中的任務(wù)取出递沪,放到對(duì)應(yīng)線程中執(zhí)行豺鼻;另外任務(wù)的取出是遵循隊(duì)列的FIFO原則:先進(jìn)先出];

> GCD基本使用

a款慨、GCD中的2個(gè)用來執(zhí)行任務(wù)的函數(shù)

// 同步方式執(zhí)行任務(wù)[queue隊(duì)列儒飒,block任務(wù)]

dispatch_sync(dispatch_queue_t queue, dispatch_block_t block);

// 異步方式執(zhí)行任務(wù)[queue隊(duì)列,block任務(wù)]

dispatch_async(dispatch_queue_t queue, dispatch_block_t block);

b檩奠、GCD同步和異步的區(qū)別

- 同步:只能在當(dāng)前線程中執(zhí)行任務(wù)桩了,不具備開啟新線程的能力;

- 異步:可以在新的線程中執(zhí)行任務(wù)埠戳,具備可啟新線程的能力井誉;

[具備開啟線程的能力,但不代表一定會(huì)開啟線程U浮?攀ァ!]

c屁使、GCD隊(duì)列的兩大類型

- 并發(fā)隊(duì)列

多個(gè)任務(wù)并發(fā)(同時(shí))執(zhí)行(自動(dòng)開啟多個(gè)線程同時(shí)執(zhí)行任務(wù))在岂;

并發(fā)功能只有在異步(dispatch_async)函數(shù)下才有效;

- 串行隊(duì)列

多個(gè)任務(wù)一個(gè)接著一個(gè)地執(zhí)行(一個(gè)任務(wù)執(zhí)行完畢后蛮寂,再執(zhí)行下一個(gè)任務(wù))蔽午;

d、容易混淆的術(shù)語(yǔ)[同步酬蹋、異步及老、并發(fā)抽莱、串行]

- 同步和異步主要影響:具不具備開啟新的線程 (并不代表一定會(huì)開線程!);

- 并行和串行主要影響:任務(wù)的執(zhí)行方式骄恶;

e岸蜗、并行隊(duì)列

- GCD默認(rèn)已經(jīng)提供了全局的并發(fā)隊(duì)列,供整個(gè)應(yīng)用使用叠蝇,不需要手動(dòng)創(chuàng)建

dispatch_get_global_queue函數(shù)獲得全局的并發(fā)隊(duì)列

dispatch_queue_t dispatch_get_global_queue(long identifier, // 隊(duì)列的優(yōu)先級(jí)

unsigned long flags); // 參數(shù)保留,用0即可

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); // 獲得全局并發(fā)隊(duì)列

- 全局并發(fā)隊(duì)列的優(yōu)先級(jí)

DISPATCH_QUEUE_PRIORITY_HIGH? ? ? 高

DISPATCH_QUEUE_PRIORITY_DEFAULT? ? 默認(rèn)(中)

DISPATCH_QUEUE_PRIORITY_LOW? ? ? ? 低

DISPATCH_QUEUE_PRIORITY_BACKGROUND 后臺(tái)

f年缎、串行隊(duì)列

- 使用dispatch_queue_create函數(shù)創(chuàng)建串行隊(duì)列

- 使用dispatch_get_main_queue()獲得主隊(duì)列(跟主線程相關(guān)的隊(duì)列悔捶,用于線程間通信)

[主隊(duì)列是GCD自帶的一種特殊串行隊(duì)列;放在主隊(duì)列中的任務(wù)单芜,都會(huì)放到主線程中執(zhí)行]

GCD蜕该、延時(shí)執(zhí)行

/** 方式1,這種延時(shí)操作是不可取的洲鸠,因?yàn)檠訒r(shí)操作是在主線程堂淡,即會(huì)卡住主線程,如果sleep在其他線程則也會(huì)卡住對(duì)應(yīng)線程*/

? 方式1 ? 延時(shí)3秒[NSThread sleepForTimeInterval:3];

? 方式2 ? 定制好任務(wù)后扒腕,不會(huì)卡住當(dāng)前線程

[self performSelector:@selector(downloadImage) withObject:nil afterDelay:3];

?方式3 ?dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{

NSLog(@"圖片下載");

});

> GCD中線程間的通信

communication

> GCD一次性代碼只執(zhí)行一次

寫單例

10,總結(jié)

11,異步+并發(fā) 開啟新線程 多個(gè)任務(wù)同時(shí)執(zhí)行

12,異步+串行 開啟新線程 任務(wù)依次同時(shí)執(zhí)行

13,同步+并發(fā) 不開啟新線程 任務(wù)依次執(zhí)行

14,同步+串行 不開新線程 任務(wù)依次執(zhí)行

15,異步+主隊(duì)列 不開啟新線程 任務(wù)依次執(zhí)行(主隊(duì)列任務(wù)是一次執(zhí)行的绢淀,并且是異步)

16,同步+主隊(duì)列 不開啟新線程 任務(wù)依次執(zhí)行(堅(jiān)決反對(duì)使用這個(gè),容易卡)

17瘾腰,pthread

18皆的,NSOperation(基于GCD封裝)

> NSOperation和NSOperationQueue實(shí)現(xiàn)多線程的具體步驟:

a、將需要執(zhí)行的操作封裝到一個(gè)NSOperation對(duì)象中蹋盆;

b费薄、然后將NSOperation對(duì)象添加到NSOperationQueue中;

c栖雾、系統(tǒng)會(huì)自動(dòng)將NSOperationQueue中的NSOperation取出來楞抡;

d、將取出來的NSOperation封裝的操作放到一條新線程中執(zhí)行析藕;

【系統(tǒng)會(huì)自動(dòng)處理召廷,不用管多少條線程】

> NSOperation的基本使用

a、NSOperation是抽象類噪径,不具備封裝操作的能力柱恤,必須使用它的子類;

b找爱、使用NSOperation子類的方式有3種

- 1梗顺,NSInvocationOperation

- 2,NSBlockOperation

- 3车摄,自定義子類繼承NSOperation寺谤,實(shí)現(xiàn)內(nèi)部相應(yīng)的方法

> NSInvocationOperation

?創(chuàng)建操作

NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(downloadImage) object:nil];

> NSBlockOperation

沒有添加到隊(duì)列中仑鸥,直接調(diào)用operation的start方法

當(dāng)任務(wù)個(gè)數(shù)為一的時(shí)候,就是同步執(zhí)行;

當(dāng)任務(wù)個(gè)數(shù)大于一的時(shí)候变屁,就會(huì)異步執(zhí)行;

手動(dòng)開啟 (沒有添加到隊(duì)列中眼俊,就需要手動(dòng)開啟)

[operation start];

添加到隊(duì)列中 [自動(dòng)異步執(zhí)行]

[queue addOperation:operation];

> NSOperationQueue

1、創(chuàng)建一個(gè)隊(duì)列(非主隊(duì)列)

NSOperationQueue *queue = [[NSOperationQueue alloc] init];

2粟关、任務(wù)任務(wù)

NSBlockOperation *operation1 = [NSBlockOperation blockOperationWithBlock:^{

NSLog(@"operation1? ? ? 下載圖片---%@",[NSThread currentThread]);

}];

[operation1 addExecutionBlock:^{

NSLog(@"operation2? ? ? 下載圖片---%@",[NSThread currentThread]);

}];

3疮胖、添加到隊(duì)列中(多個(gè)任務(wù)會(huì)自動(dòng)異步執(zhí)行任務(wù),并發(fā))

[queue addOperation:operation1];

// 更為簡(jiǎn)單的寫法? 自動(dòng)異步執(zhí)行任務(wù)闷板,并發(fā)

NSOperationQueue *queue = [[NSOperationQueue alloc] init];

[queue addOperationWithBlock:^{

NSLog(@"operation3? ? ? 下載圖片---%@",[NSThread currentThread]);

}];

設(shè)置最大并發(fā)數(shù)[這可以更好的保證程序的性能]澎灸,即控制并發(fā)執(zhí)行最大線程數(shù)量,以節(jié)省內(nèi)存空間

queue.maxConcurrentOperationCount = 2;

a遮晚、NSOperation之間可以設(shè)置依賴來保證執(zhí)行順序(注意不能相互依賴)性昭;

添加依賴 (和添加到隊(duì)列的先后順序無關(guān))

[operationC addDependency:operationB];

[operationB addDependency:operationA];

b、可以在不同queue中的NSOperation之間創(chuàng)建依賴县遣;

> 線程間通信 回到主線程設(shè)置顯示


> 隊(duì)列的取消糜颠、暫停、恢復(fù)

a萧求、取消隊(duì)列的所有操作

- (void)cancelAllOperations其兴; 【在內(nèi)存警告的時(shí)候可以添加上該方法】

[也可以調(diào)用NSOperation的- (void)cancel方法取消單個(gè)操作]

b、暫停和恢復(fù)隊(duì)列

- (void)SetSuspended:(BOOL)b; 【YES表示暫停隊(duì)列饭聚,NO表示恢復(fù)隊(duì)列】

[滾動(dòng)視圖(注意表格視圖也是繼承自UIScrollView的)性能優(yōu)化中可以使用到忌警,開始拖動(dòng)的時(shí)候暫停隊(duì)列下載,拖動(dòng)結(jié)束后恢復(fù)隊(duì)列]

接收到內(nèi)存警告

- (void)didReceiveMemoryWarning{

[super didReceiveMemoryWarning];

// 取消隊(duì)列操作

}

- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView{

//開始拖動(dòng)秒梳,暫停隊(duì)列操作

}

- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate{

// 結(jié)束拖動(dòng)法绵,恢復(fù)隊(duì)列操作

}

(5) 線程安全(在GCD以后,已經(jīng)幫我們處理了這些問題)

?線程安全問題

實(shí)例:3個(gè)窗口賣票

> 3個(gè)窗口同時(shí)賣票酪碘,即多條線程訪問同一資源;

> 線程哪個(gè)先調(diào)用是不確定的朋譬,先調(diào)度誰是CPU的事;

> 當(dāng)線程任務(wù)執(zhí)行完成兴垦,線程為死亡態(tài)(如果是沒有while循環(huán)徙赢,但第二次點(diǎn)擊的時(shí)候程序就崩潰);

> 多線程的安全隱患

a探越、資源共享(資源搶占):一塊資源可能會(huì)被多個(gè)線程共享(即多個(gè)線程可能訪問一個(gè)資源)狡赐;

(當(dāng)多個(gè)線程訪問同一塊資源時(shí),很容易引發(fā)數(shù)據(jù)錯(cuò)亂和數(shù)據(jù)安全的問題)[例如一個(gè)線程取錢钦幔,一個(gè)線程存錢枕屉;例如賣票,多個(gè)窗口賣票即多條線程賣]

> 互斥鎖的使用

a鲤氢、互斥鎖方式一:@synchronized(鎖對(duì)象){//需要加鎖的代碼}

// 鎖定一份代碼只用一把鎖搀擂,用多把鎖是無效的;

b西潘、互斥鎖方式二:

/** 1、互斥鎖的初始化*/

_myLock = [[NSLock alloc] init];

// 2哨颂、加鎖方式2

[_myLock lock];

// 需要加鎖的代碼

// 3喷市、解鎖

[_myLock unlock];

> 互斥鎖的優(yōu)缺點(diǎn)

優(yōu)點(diǎn):能有效防止因多線程搶奪資源造成的數(shù)據(jù)安全問題;

缺點(diǎn):需要消耗大量CPU資源威恼;

> 互斥鎖使用的前提:多條線程搶占同一資源品姓;

> 單例的線程安全

> 數(shù)據(jù)庫(kù)操作的線程安全

nonatomic(atomic):指定set、get方法是否原子操作箫措。原子操作缭黔,主要指是否線程安全。如果使用atomic那么set蒂破、get方法都是線程安全的--- 當(dāng)一個(gè)線程進(jìn)入get、set方法之后别渔,其他線程無法進(jìn)入該set附迷、get方法,那么久避免多線程并發(fā)破壞數(shù)據(jù)完整性哎媚,atomic是默認(rèn)值喇伯。雖然atomic可以保證對(duì)象數(shù)據(jù)的完整性,但atomic線程安全會(huì)造成性能下降(因?yàn)闀?huì)導(dǎo)致其他線程的阻塞)拨与。因此稻据,大多數(shù)單線程環(huán)境下,都是使用nonatomic來提高set买喧、get方法的訪問性能;

線程注意點(diǎn):

1捻悯、不要同時(shí)開太多線程(1~3條線程即可,不要超過5條);

2淤毛、線程概念:

主線程:UI線程今缚,顯示、刷新UI界面低淡,處理UI控件事件姓言;

子線程:后臺(tái)線程,異步線程蔗蹋;

3何荚、不要把耗時(shí)操作放在主線程,要放在子線程中執(zhí)行猪杭;

19.GCD使用

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末餐塘,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子胁孙,更是在濱河造成了極大的恐慌唠倦,老刑警劉巖称鳞,帶你破解...
    沈念sama閱讀 211,123評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異稠鼻,居然都是意外死亡冈止,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,031評(píng)論 2 384
  • 文/潘曉璐 我一進(jìn)店門候齿,熙熙樓的掌柜王于貴愁眉苦臉地迎上來熙暴,“玉大人,你說我怎么就攤上這事慌盯≈苊梗” “怎么了?”我有些...
    開封第一講書人閱讀 156,723評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵亚皂,是天一觀的道長(zhǎng)俱箱。 經(jīng)常有香客問我,道長(zhǎng)灭必,這世上最難降的妖魔是什么狞谱? 我笑而不...
    開封第一講書人閱讀 56,357評(píng)論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮禁漓,結(jié)果婚禮上跟衅,老公的妹妹穿的比我還像新娘。我一直安慰自己播歼,他們只是感情好伶跷,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,412評(píng)論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著秘狞,像睡著了一般叭莫。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上烁试,一...
    開封第一講書人閱讀 49,760評(píng)論 1 289
  • 那天食寡,我揣著相機(jī)與錄音,去河邊找鬼廓潜。 笑死抵皱,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的辩蛋。 我是一名探鬼主播呻畸,決...
    沈念sama閱讀 38,904評(píng)論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼悼院!你這毒婦竟也來了伤为?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,672評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎绞愚,沒想到半個(gè)月后叙甸,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,118評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡位衩,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,456評(píng)論 2 325
  • 正文 我和宋清朗相戀三年裆蒸,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片糖驴。...
    茶點(diǎn)故事閱讀 38,599評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡僚祷,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出贮缕,到底是詐尸還是另有隱情辙谜,我是刑警寧澤,帶...
    沈念sama閱讀 34,264評(píng)論 4 328
  • 正文 年R本政府宣布感昼,位于F島的核電站装哆,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏定嗓。R本人自食惡果不足惜烂琴,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,857評(píng)論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望蜕乡。 院中可真熱鬧,春花似錦梗夸、人聲如沸层玲。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,731評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)辛块。三九已至,卻和暖如春铅碍,著一層夾襖步出監(jiān)牢的瞬間润绵,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,956評(píng)論 1 264
  • 我被黑心中介騙來泰國(guó)打工胞谈, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留尘盼,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,286評(píng)論 2 360
  • 正文 我出身青樓烦绳,卻偏偏與公主長(zhǎng)得像卿捎,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子径密,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,465評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容