iOS-----線程

1.什么是進程刁赖?

進程是指在一個系統(tǒng)內(nèi)正在運行的一個應(yīng)用程序揍拆。每個進程之間是獨立的芽淡,每個進程均運行在其專用且受保護的內(nèi)存空間內(nèi)。比如同時打開兩個應(yīng)用支付寶和微信择示,系統(tǒng)就會分別啟動2個進程束凑。

2.什么是線程?

1個進程如果想要執(zhí)行任務(wù)栅盲,必須要有線程(每一個進程至少要有一個線程)

線程是進程的基本執(zhí)行單元汪诉,一個進程(程序)的所有任務(wù)必須要在線程中執(zhí)行

3.線程的串行

一個線程中的任務(wù)的執(zhí)行是串行的,如果要在一個線程中執(zhí)行多個任務(wù)谈秫,只能一個一個地桉順序執(zhí)行扒寄;換句話說,在同一時間內(nèi)孝常,一個線程只能執(zhí)行一個任務(wù)旗们。

4.什么是多線程

一個進程中可以開啟多條線程,每條線程并行(同時)執(zhí)行不同的任務(wù)

優(yōu)點:多線程可以提供程序的執(zhí)行效率

5.多線程的原理

同一時間构灸,CPU只能處理一條線程上渴,只有一條線程在工作(執(zhí)行),當多線程并發(fā)(同時)執(zhí)行喜颁,實質(zhì)也就是CPU快速地在多條線程之間調(diào)度(切換)

如果CPU調(diào)度線程的時間足夠快稠氮,就會造成了多線程并發(fā)執(zhí)行的假象。如果線程非常的多半开,CPU將會在N多線程之間調(diào)度隔披,CPU會被活活累死,消耗大量的CPU資源寂拆,這樣也就導(dǎo)致了每條線程被調(diào)度執(zhí)行的頻次會降低奢米,即線程的執(zhí)行效率降低

6.多線程的優(yōu)點:

不僅能適當提高程序的執(zhí)行效率抓韩,還能提高資源利用率,如CPU鬓长、內(nèi)存的利用率

7.多線程的缺點:

開啟多線程需要占用一定的內(nèi)存空間:默認情況下谒拴,主線程占用1M,子線程占用512KB涉波,如果開啟大量的線程英上,或占用大量的內(nèi)存空間,降低程序的性能啤覆。如果線程的數(shù)量很多苍日,不止會使CPU在調(diào)度線程上的開銷增大,也會使得程序設(shè)計更加復(fù)雜:如線程間的通信和數(shù)據(jù)共享等窗声。

8.多線程的應(yīng)用:

主線程:一個iOS程序運行后相恃,默認會開啟一條線程,這條線程就被稱為"主線程"和"UI線程"

主線程的作用:顯示\刷新UI界面以及處理UI事件(如:點擊事件笨觅、滾動事件豆茫、拖拽事件等)

主線程的使用注意事項:不要把比較耗時的操作放到主線程中。因為耗時的操作會卡住主線程屋摇,對UI的流暢度造成嚴重的影響,給用戶一種"卡"的壞體驗

//8.1多線程的安全隱患

//8.1.1資源共享:

一塊資源可能會被多個線程共享幽邓,也就是多個線程可能會訪問同一塊資源炮温。如多個線程訪問同一個對象或者同一個變量,再或者是同一個文件牵舵。當多個線程訪問同一塊資源時柒啤,很容易造成引發(fā)數(shù)據(jù)錯亂和數(shù)據(jù)安全的問題

8.1.2-----解決辦法

互斥鎖使用格式---

@synchronized (鎖對象) {

//需要鎖定的代碼

}

注意:鎖定一份代碼只用一把鎖,用多把鎖是無效的

互斥鎖的優(yōu)缺點:

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

缺點:需要消耗大量的CPU資源

互斥鎖使用的前提是:多條線程去搶奪同一塊資源

9.創(chuàng)建線程

1.一個NSThread對象就代表一條線程畸颅,

1.1->創(chuàng)建和啟動線程

//創(chuàng)建線程

NSThread* thread = [[NSThread alloc]initWithTarget:self selector:@selector(initThread) object:nil];

//啟動線程

[thread start];

//特點:線程一啟動担巩,就會在線程thread中執(zhí)行self的initThread方法

//2--主線程的相關(guān)用法:

//2.1-------------是否為主線程

//? ? @property (readonly) BOOL isMainThread NS_AVAILABLE(10_5, 2_0);

//thread.isMainThread

//2.2-------------是否為主線程

//? ? @property (class, readonly) BOOL isMainThread NS_AVAILABLE(10_5, 2_0); // reports whether current thread is main

//屬性用法? ? [NSThread isMainThread];

//2.3-------------獲得主線程

//? ? @property (class, readonly, strong) NSThread *mainThread NS_AVAILABLE(10_5, 2_0);

//屬性用法[NSThread mainThread];

//2.4---線程的調(diào)度優(yōu)先級:調(diào)度優(yōu)先級的取值范圍是0.0~1.0,默認0.5没炒,值越大涛癌,優(yōu)先級越高

//? ? + (double)threadPriority;

//? ? + (BOOL)setThreadPriority:(double)p;

//設(shè)置線程的名字

// 2.5---? @property (nullable, copy) NSString *name NS_AVAILABLE(10_5, 2_0);

//3-----其他創(chuàng)建線程的方式

//3.1----創(chuàng)建線程后自動啟動線程

//+ (void)detachNewThreadSelector:(SEL)selector toTarget:(id)target withObject:(nullable id)argument;

//3.2----隱式創(chuàng)建并啟動線程

//? ? [self performSelectorInBackground:@selector(initThread) withObject:nil];

//上述2種創(chuàng)建線程的優(yōu)缺點:優(yōu)點是簡單快捷,缺點是無法對線程進行更詳細的設(shè)置送火。


當前流程繼續(xù)performSelector關(guān)于內(nèi)存管理的執(zhí)行原理是這樣的執(zhí)行 [self performSelector:@selector(method1:) withObject:self.tableLayer afterDelay:3]; 的時候拳话,系統(tǒng)會將tableLayer的引用計數(shù)加1,執(zhí)行完這個方法時种吸,還會將tableLayer的引用計數(shù)減1弃衍,由于延遲這時tableLayer的引用計數(shù)沒有減少到0,也就導(dǎo)致了切換場景dealloc方法沒有被調(diào)用坚俗,出現(xiàn)了內(nèi)存泄露镜盯。

利用如下函數(shù):

[NSObject cancelPreviousPerformRequestsWithTarget:self]

當然你也可以一個一個得這樣用:

[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(method1:) object:nil]

加上了這個以后岸裙,順利地執(zhí)行了dealloc方法

4. 線程間的通信

4.1---線程間通信的含義:在一個進程中,線程往往不是孤立存在的速缆,多個線程之間需要經(jīng)常進行通信

4.2---線程間通信的體現(xiàn):一個線程給另一個線程傳遞數(shù)據(jù)或者一個線程執(zhí)行完之后去執(zhí)行另一個線程

4.3---- 線程間通信的常用方法

- (void)performSelectorOnMainThread:(SEL)aSelector withObject:(id)arg waitUntilDone:(BOOL)wait;

- (void)performSelector:(SEL)aSelector onThread:(NSThread *)thr withObject:(id)arg waitUntilDone:(BOOL)wait;

4.4---從子線程回到主線程

dispatch_async( dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

// 執(zhí)?耗時的異步操作...

dispatch_async(dispatch_get_main_queue(), ^{

// 回到主線程,執(zhí)?UI刷新操作

});

});

或者

dispatch_async( dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

// 執(zhí)?耗時的異步操作...

// 回到主線程,執(zhí)?UI刷新操作

[self.imageView performSelectorOnMainThread:@selector(方法) withObject:image waitUntilDone:NO];

});

5.GCD:Grand Central Dispatch

5.1--GCD是純C語言降允,提供了非常強大的函數(shù)

5.2---GCD的優(yōu)勢:

GCD是蘋果公司為多核的并行運算提出的解決方案

GCD會自動利用更多的CPU內(nèi)核(比如雙核、四核)

GCD會自動管理線程的生命周期(創(chuàng)建線程激涤、調(diào)度任務(wù)拟糕、銷毀線程)

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

5.3-------

GCD的兩個核心概念:

5.3.1--任務(wù):執(zhí)行什么操作

5.3.2--隊列:用來存放任務(wù)

GCD的使用就兩個步驟:

1->定制任務(wù)

2->確定想要做的事情

將任務(wù)添加到隊列中倦踢,GCD會自動將隊列中的任務(wù)取出送滞,放到對應(yīng)的線程中執(zhí)行

重點:任務(wù)的取出遵循隊列的FIFO原則:先進先出,后進后出

5.4---執(zhí)行任務(wù)

5.4.1----GCD中有兩個用來執(zhí)行任務(wù)的函數(shù)辱挥。特別說明:把右邊的參數(shù)(任務(wù)-<#^(void)block#>)提交給左邊的參數(shù)(隊列:<#dispatch_queue_t? _Nonnull queue#>)進行執(zhí)行

第一種:用同步的方式執(zhí)行任務(wù)? ? dispatch_sync(<#dispatch_queue_t? _Nonnull queue#>, <#^(void)block#>)

參數(shù)說明:queue:隊列? ? ? ? block:任務(wù)

第二種:用異步的方式執(zhí)行任務(wù)dispatch_async(<#dispatch_queue_t? _Nonnull queue#>, <#^(void)block#>)

5.4.2---同步和異步的區(qū)別

同步:在當前線程中執(zhí)行任務(wù)犁嗅,其并不具備開啟新線程的能力

異步:在另一條線程中執(zhí)行任務(wù),它具備了開啟新線程的能力

5.5---隊列

GCD的隊列類型可以分為兩種類型:

1->并發(fā)隊列:可以讓多個任務(wù)并發(fā)(同時)執(zhí)行(會自動開啟多個線程同時執(zhí)行任務(wù))晤碘,并發(fā)功能只有在異步:dispatch_async函數(shù)下才是有效的

GCD默認已經(jīng)提供了全局的并發(fā)隊列褂微,供整個應(yīng)用使用,不需要手動創(chuàng)建

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

dispatch_queue_t dispatch_get_global_queue(dispatch_queue_priority_t priority,unsigned long flags); // 此參數(shù)暫時無用园爷,用0即可

示例:

這個參數(shù)是留給以后用的宠蚂,暫時用不上,傳個0童社。

第一個參數(shù)為優(yōu)先級求厕,這里選擇默認的。獲取一個全局的默認優(yōu)先級的并發(fā)隊列扰楼。

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

說明:全局并發(fā)隊列的優(yōu)先級

#define DISPATCH_QUEUE_PRIORITY_HIGH 2 // 高

#define DISPATCH_QUEUE_PRIORITY_DEFAULT 0 // 默認(中)

#define DISPATCH_QUEUE_PRIORITY_LOW (-2) // 低

#define DISPATCH_QUEUE_PRIORITY_BACKGROUND INT16_MIN // 后臺

2->串行隊列:讓任務(wù)一個接著一個的執(zhí)行呀癣,即一個任務(wù)執(zhí)行完了,再去執(zhí)行另一個任務(wù)

GCD中獲得串行有兩種方法:

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

dispatch_queue_t? dispatch_queue_create(const char *label,? dispatch_queue_attr_t attr); // 隊列名稱弦赖, 隊列屬性项栏,一般用NULL即可

隊列名稱的作用:

將來調(diào)試的時候,可以看得出任務(wù)是在哪個隊列中執(zhí)行的蹬竖。

示例:

dispatch_queue_t queue = dispatch_queue_create("wendingding", NULL); // 創(chuàng)建

dispatch_release(queue); // 非ARC需要釋放手動創(chuàng)建的隊列

1.2-> 使用主隊列(跟主線程相關(guān)聯(lián)的隊列)

主隊列是GCD自帶的一種特殊的串行隊列,放在主隊列中的任務(wù)沼沈,都會放到主線程中執(zhí)行

使用dispatch_get_main_queue()獲得主隊列

示例:dispatch_queue_t queue = dispatch_get_main_queue();

小結(jié)

說明:同步函數(shù)不具備開啟線程的能力,無論是什么隊列都不會開啟線程币厕;異步函數(shù)具備開啟線程的能力庆冕,開啟幾條線程由隊列決定(串行隊列只會開啟一條新的線程,并發(fā)隊列會開啟多條線程)劈榨。

//iOS的延時操作

/*

iOS常見的延時操作有兩種方法:

1.調(diào)用NSObject的方法: [self performSelector:@selector(initThread) withObject:nil afterDelay:2.0];

2秒后調(diào)用self的initThread方法访递,該方法在那個線程調(diào)用,那么run就在哪個線程執(zhí)行(當前線程)同辣,通常是主線程拷姿。

2.使用GCD函數(shù)

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{

//2秒后執(zhí)行這里

});

如果隊列是主隊列惭载,那么就在主線程執(zhí)行,如果隊列是并發(fā)隊列响巢,那么會新開啟一個線程描滔,在子線程中執(zhí)行。


/*

NSOperation

1.---- NSOperation的作用:配合使用NSOperation和NSOperationQueue也能實現(xiàn)多線程編程

其實現(xiàn)多線程的具體步驟:

1.1->將要執(zhí)行的操作封裝到一個NSOperation對象中

1.2->將NSOperation對象添加到NSOperationQueue中

1.3->系統(tǒng)會自動將NSOperationQueue中的NSOperation取出來

1.4->將取出的NSOperation封裝的操作放到一條新線程中執(zhí)行

2----NSOperation的子類

NSOperation是一個抽象類踪古,并不具備封裝操作的能力含长,一定要使用他的子類才可以

使用NSOperationi子類的方式有三種:

(1)NSInvocationOperation

(2)NSBlockOperation

(3)自定義子類繼承NSOperation,實現(xiàn)內(nèi)部相應(yīng)的?法

3.---創(chuàng)建操作對象,封裝要執(zhí)行的任務(wù)

3.1->NSInvocationOperation

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

//執(zhí)行操作

[operation start];

//說明:一旦執(zhí)行操作伏穆,就會調(diào)用target的initThread方法

重點:操作對象默認在主線程中執(zhí)行拘泞,只有添加到隊列中才會開啟新的線程。即默認情況下枕扫,如果操作沒有放到隊列中queue中陪腌,都是同步執(zhí)行。只有將NSOperation放到一個NSOperationQueue中,才會異步執(zhí)行操作

3.2->--NSBlockOperation

//封裝操作

//創(chuàng)建NSBlockOperation操作對象

NSBlockOperation* operation = [NSBlockOperation blockOperationWithBlock:^{

}];

//添加操作

[operation addExecutionBlock:^{

}];

//開啟執(zhí)行操作

[operation start];

//重點:只要NSBlockOperation封裝的操作數(shù)大于一烟瞧,就會異步執(zhí)行操作

4.NSOperationQueue

NSOperationQueue的作用:NSOperation可以調(diào)用start方法來執(zhí)行任務(wù)诗鸭,但默認是同步執(zhí)行的,如果將NSOperation添加到NSOperationQueue(操作隊列)中,系統(tǒng)會自動異步執(zhí)行NSOperation中的操作参滴,自動開啟線程

NSBlockOperation* operation = [NSBlockOperation blockOperationWithBlock:^{

}];

//添加操作

[operation addExecutionBlock:^{

}];

//創(chuàng)建NSOperationQueue

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

//把操作添加到隊列中

//第一種添加方式:

[queue addOperation:operation];

//第二種添加方式:

[queue addOperationWithBlock:^{

}];

重點:系統(tǒng)自動將NSOperationqueue中的NSOperation對象取出强岸,將其封裝的操作放到一條新的線程中執(zhí)行。


NSOperation基本操作

1.->并發(fā)數(shù):同時執(zhí)行的任務(wù)數(shù)砾赔,如果同時開啟3個線程執(zhí)行3個任務(wù)请唱,那并發(fā)數(shù)就是3了

2-> 最大并發(fā)數(shù):同一時間最多只能執(zhí)行的任務(wù)個數(shù)

3-> 最大并發(fā)數(shù)的相關(guān)方法

- (NSInteger)maxConcurrentOperationCount;

- (void)setMaxConcurrentOperationCount:(NSInteger)cnt;

特別說明:如果沒有設(shè)置最大并發(fā)數(shù),那么并發(fā)的個數(shù)會有系統(tǒng)內(nèi)存和CPU決定过蹂,

溫馨提示:最大并發(fā)數(shù)不要亂寫,最好5以內(nèi)聚至,一般以2~3為宜酷勺,因為雖然任務(wù)是在子線程進行處理的,但是CPU處理這些過多的子線程可能會影響UI扳躬,讓UI變卡脆诉。

隊列的取消,暫停和恢復(fù)

1->取消隊列的所有操作

- (void)cancelAllOperations;

提?:也可以調(diào)用NSOperation的- (void)cancel?法取消單個操作

2->暫停和恢復(fù)隊列

- (void)setSuspended:(BOOL)b; // YES代表暫停隊列,NO代表恢復(fù)隊列

- (BOOL)isSuspended; //當前狀態(tài)

3->暫停和恢復(fù)的適用場合:在tableview界面贷币,開線程下載遠程的網(wǎng)絡(luò)界面击胜,對UI會有影響,使用戶體驗變差役纹。那么這種情況偶摔,就可以設(shè)置在用戶操作UI(如滾動屏幕)的時候,暫停隊列(不是取消隊列)促脉,停止?jié)L動的時候辰斋,恢復(fù)隊列策州。

操作優(yōu)先級

1->設(shè)置NSOperation在queue中的優(yōu)先級,可以改變操作的執(zhí)?優(yōu)先級

- (NSOperationQueuePriority)queuePriority;

- (void)setQueuePriority:(NSOperationQueuePriority)p;

(2)優(yōu)先級的取值

NSOperationQueuePriorityVeryLow = -8L,

NSOperationQueuePriorityLow = -4L,

NSOperationQueuePriorityNormal = 0,

NSOperationQueuePriorityHigh = 4,

NSOperationQueuePriorityVeryHigh = 8

說明:優(yōu)先級高的任務(wù),調(diào)用的幾率會更大宫仗。

操作依賴

NSOperation之間可以設(shè)置依賴來保證執(zhí)行順序够挂,?如一定要讓操作A執(zhí)行完后,才能執(zhí)行操作B,可以像下面這么寫

[operationB addDependency:operationA]; // 操作B依賴于操作

但是不能循環(huán)依賴

重點:任務(wù)添加的順序并不能夠決定執(zhí)行順序,執(zhí)行的順序取決于依賴藕夫。使用Operation的目的就是為了讓開發(fā)人員不再關(guān)心線程孽糖。

操作的監(jiān)聽:

可以監(jiān)聽一個操作的執(zhí)行完畢

- (void (^)(void))completionBlock;

- (void)setCompletionBlock:(void (^)(void))block;

第一種方式:可以直接跟在任務(wù)后面編寫需要完成的操作,如這里在下載圖片后毅贮,緊跟著下載第二張圖片办悟。但是這種寫法有的時候把兩個不相關(guān)的操作寫到了一個代碼塊中,代碼的可閱讀性不強嫩码。

第二種方式:? 在上一個任務(wù)執(zhí)行完后誉尖,會執(zhí)行operation.completionBlock=^{}代碼段,且是在當前線程執(zhí)行铸题。

*/

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末铡恕,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子丢间,更是在濱河造成了極大的恐慌探熔,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,627評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件烘挫,死亡現(xiàn)場離奇詭異诀艰,居然都是意外死亡,警方通過查閱死者的電腦和手機饮六,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,180評論 3 399
  • 文/潘曉璐 我一進店門其垄,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人卤橄,你說我怎么就攤上這事绿满。” “怎么了窟扑?”我有些...
    開封第一講書人閱讀 169,346評論 0 362
  • 文/不壞的土叔 我叫張陵喇颁,是天一觀的道長。 經(jīng)常有香客問我嚎货,道長橘霎,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 60,097評論 1 300
  • 正文 為了忘掉前任殖属,我火速辦了婚禮姐叁,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己七蜘,他們只是感情好谭溉,可當我...
    茶點故事閱讀 69,100評論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著橡卤,像睡著了一般扮念。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上碧库,一...
    開封第一講書人閱讀 52,696評論 1 312
  • 那天柜与,我揣著相機與錄音,去河邊找鬼嵌灰。 笑死弄匕,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 41,165評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼芋忿,長吁一口氣:“原來是場噩夢啊……” “哼纠脾!你這毒婦竟也來了队魏?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 40,108評論 0 277
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后亡哄,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,646評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡布疙,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,709評論 3 342
  • 正文 我和宋清朗相戀三年蚊惯,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片灵临。...
    茶點故事閱讀 40,861評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡截型,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出儒溉,到底是詐尸還是另有隱情宦焦,我是刑警寧澤,帶...
    沈念sama閱讀 36,527評論 5 351
  • 正文 年R本政府宣布睁搭,位于F島的核電站,受9級特大地震影響笼平,放射性物質(zhì)發(fā)生泄漏园骆。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 42,196評論 3 336
  • 文/蒙蒙 一寓调、第九天 我趴在偏房一處隱蔽的房頂上張望锌唾。 院中可真熱鬧,春花似錦、人聲如沸晌涕。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,698評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽余黎。三九已至重窟,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間惧财,已是汗流浹背巡扇。 一陣腳步聲響...
    開封第一講書人閱讀 33,804評論 1 274
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留垮衷,地道東北人厅翔。 一個月前我還...
    沈念sama閱讀 49,287評論 3 379
  • 正文 我出身青樓,卻偏偏與公主長得像搀突,于是被迫代替她去往敵國和親刀闷。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,860評論 2 361

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