你好,GCD

1. 并行和并發(fā)有什么區(qū)別?

并行:同一時(shí)刻同時(shí)執(zhí)行不同的任務(wù), 關(guān)鍵點(diǎn)在于同時(shí), 當(dāng)然想達(dá)到這一點(diǎn)至少有兩條線程;

并發(fā):同一時(shí)間段可以執(zhí)行不同的任務(wù), 關(guān)鍵在于 可以執(zhí)行不同的任務(wù), 想做到這一點(diǎn) 一條線程也可以,因?yàn)榭梢栽谝粭l線程中交替執(zhí)行, 多條線程也可以達(dá)到, 不同的線程中執(zhí)行不同的任務(wù);

2. 線程和進(jìn)程?

進(jìn)程:具有獨(dú)立功能的關(guān)于某個(gè)數(shù)據(jù)集合上的第一次運(yùn)行活動(dòng),是系統(tǒng)資源分配和調(diào)度的獨(dú)立單位;
線程:是進(jìn)程的一個(gè)實(shí)體,是CPU調(diào)度和分派的基本代為,它與同一進(jìn)程中的其他線程共享該進(jìn)程中所有資源;
區(qū)別:
1,一個(gè)程序至少一個(gè)進(jìn)程,一個(gè)進(jìn)程至少有一個(gè)線程;
2, 進(jìn)程在執(zhí)行過(guò)程中擁有獨(dú)立的內(nèi)存單元,而多個(gè)線程共享內(nèi)存悯舟,從而極大地提高了程序的運(yùn)行效率
3, 線程的劃分尺度小于進(jìn)程担租,使得多線程程序的并發(fā)性高進(jìn)程只能在一個(gè)時(shí)間干一件事,如果想同時(shí)干兩件事或多件事抵怎,進(jìn)程就無(wú)能為力了,同一個(gè)進(jìn)程中的多個(gè)線程之間可以并發(fā)執(zhí)行

收拾下心情,進(jìn)入我們的主角GCD:

1奋救、為什么要用GCD?

  • GCD會(huì)自動(dòng)幫我們管理線程的生命周期,它內(nèi)部維護(hù)著一個(gè)線程池;
  • 它可以更好的利用多核CPU;
  • 使用起來(lái)方便,我們只需要將需要執(zhí)行的任務(wù)放入block就可以了;

2、如何更好的理解任務(wù)和隊(duì)列;

任務(wù):你讓程序干的事情,也就是程序需要執(zhí)行哪些操作;GCD中通常block里面就是一系列的任務(wù);]

任務(wù)

隊(duì)列:隊(duì)列是用來(lái)裝任務(wù)的,管理任務(wù)的,不然任務(wù)就亂套了; 它采用FIFO先進(jìn)先出的原則,不管是串行隊(duì)列還是并發(fā)隊(duì)列都是一樣的,注意這里僅僅指的是出隊(duì)列的順序!!!

隊(duì)列
如圖:任務(wù)4反惕、3尝艘、2、1依次放入隊(duì)列中,那么任務(wù)出去的順序是4姿染、3背亥、2、1;

串行隊(duì)列: 隊(duì)列中的任務(wù)只能一個(gè)個(gè)執(zhí)行,前面一個(gè)沒(méi)有執(zhí)行完,后面一個(gè)不能執(zhí)行;

串行隊(duì)列

并發(fā)隊(duì)列: 前面一個(gè)任務(wù)出隊(duì)列開(kāi)始執(zhí)行的時(shí)候,后面一個(gè)就 可以 在新的線程去執(zhí)行了,注意這里是可以,表示一種能力,不一定會(huì)這樣;

并發(fā)隊(duì)列
后面一個(gè)任務(wù)看到前面一個(gè)在開(kāi)始執(zhí)行狀態(tài)就可以出隊(duì)列,準(zhǔn)備開(kāi)始執(zhí)行了

3悬赏、同步和異步

同步:

  • 不開(kāi)啟新的線程就在當(dāng)前線程執(zhí)行,
  • 必須等block里面的代碼執(zhí)行完,dispathch才會(huì)返回;執(zhí)行后面的,會(huì)阻塞當(dāng)前線程;

異步:

  • 可以開(kāi)啟新的線程,注意是可以 并不一定會(huì),它有這個(gè)能力;
  • 不需要等block里面的代碼執(zhí)行完,立即返回,不會(huì)阻塞當(dāng)前線程;

4狡汉、一個(gè)關(guān)于GCD的故事(本故事純屬本人虛構(gòu),如果有不恰當(dāng)?shù)牡胤酱磥?lái)改正)

有兩個(gè)咖啡店,咖啡店1只有一個(gè)窗口賣(mài), 咖啡店2有很多窗口賣(mài), 然后兩個(gè)老師都帶著 排著一條長(zhǎng)隊(duì)的 同學(xué)去買(mǎi)咖啡, 其中一個(gè)老師A告訴她的學(xué)生,你們等前面一個(gè)買(mǎi)好再接著買(mǎi),另一個(gè)老師B告訴她的學(xué)生,你前面的同學(xué)開(kāi)始買(mǎi)選咖啡的時(shí)候,下一個(gè)就可以去找其他窗口開(kāi)始買(mǎi)了,不要等的;

  • A老師把她的同學(xué)帶到了咖啡店1:
    學(xué)生們是只能等前面買(mǎi)好才能買(mǎi)的,而且就只有一個(gè)窗口, 所以結(jié)果:一個(gè)接一個(gè)按順序買(mǎi)就好
  • A老師把她的同學(xué)帶到了咖啡店2:
    前面一個(gè)同學(xué)正在買(mǎi)的時(shí)候,后面一個(gè)想去找其他窗口開(kāi)始買(mǎi),但是現(xiàn)實(shí)告訴他沒(méi)有其他窗口了,老老實(shí)實(shí)等前面一個(gè)買(mǎi)好吧,,,,,所以結(jié)果:一個(gè)接一個(gè)按順序買(mǎi)就好

  • B老師把她的同學(xué)帶到了咖啡店1:
    雖然現(xiàn)實(shí)很好,有好多窗口賣(mài)咖啡,但是 學(xué)生都是乖孩子,有紀(jì)律的,前面一個(gè)買(mǎi)好后面才能買(mǎi),所以就只需要去其他窗口中的一個(gè)窗口買(mǎi)就好了,結(jié)果:一個(gè)接一個(gè)按順序買(mǎi)就好

  • B老師把她的同學(xué)帶到了咖啡店2:
    這里的孩紙是最幸運(yùn)的,天時(shí)地利人和; 學(xué)生可以找其他窗口買(mǎi),而且這里恰好就有好多窗口,他們幾乎同時(shí)的在不同的窗戶(hù)買(mǎi)起咖啡來(lái); 結(jié)果:同時(shí)買(mǎi);

5、GCD中的六種組合方式

一. 串行隊(duì)列 + 同步執(zhí)行

- (void) GCDTest1
{
    
    dispatch_queue_t queue = dispatch_queue_create("serialQueue.xj.com", DISPATCH_QUEUE_SERIAL);
    
    dispatch_sync(queue, ^{
        
        NSLog(@"1------>>>%@",[NSThread currentThread]);
       
    });
    
    dispatch_sync(queue, ^{
        
        NSLog(@"2------>>>%@",[NSThread currentThread]);
        
    });
    
    dispatch_sync(queue, ^{
        
        NSLog(@"3------>>>%@",[NSThread currentThread]);
       
    });
    
        NSLog(@"4------>>>%@",[NSThread currentThread]);
    
}

結(jié)果:

2018-04-01 10:16:17.186574+0800 GCD[55764:12462142] 1------>>><NSThread: 0x604000261c00>{number = 1, name = main}
2018-04-01 10:16:17.186850+0800 GCD[55764:12462142] 2------>>><NSThread: 0x604000261c00>{number = 1, name = main}
2018-04-01 10:16:17.187063+0800 GCD[55764:12462142] 3------>>><NSThread: 0x604000261c00>{number = 1, name = main}
2018-04-01 10:16:17.187228+0800 GCD[55764:12462142] 4------>>><NSThread: 0x604000261c00>{number = 1, name = main}

分析:
這里對(duì)應(yīng)上面故事的第一種情況,由于是同步,不開(kāi)線程,當(dāng)前線程為主線程,所以所有任務(wù)都在主線程中執(zhí)行,又因?yàn)槭谴嘘?duì)列,任務(wù)按順序依次執(zhí)行,而且還是同步,每次需等block內(nèi)執(zhí)行完,所以順序是1-->2--->3--->4;

二. 串行隊(duì)列 + 異步執(zhí)行

- (void) GCDTest2
{
    
    dispatch_queue_t queue = dispatch_queue_create("serialQueue.xj.com", DISPATCH_QUEUE_SERIAL);
    
    dispatch_async(queue, ^{
        
        NSLog(@"1------>>>%@",[NSThread currentThread]);
        
    });
    
    dispatch_async(queue, ^{
        
        NSLog(@"2------>>>%@",[NSThread currentThread]);
        
    });
    
    dispatch_async(queue, ^{
        
        NSLog(@"3------>>>%@",[NSThread currentThread]);
        
    });
    
    NSLog(@"4------>>>%@",[NSThread currentThread]);
    
}

結(jié)果:

2018-04-01 10:22:41.780449+0800 GCD[56160:12471344] 4------>>><NSThread: 0x604000079940>{number = 1, name = main}
2018-04-01 10:22:41.780478+0800 GCD[56160:12471596] 1------>>><NSThread: 0x60400027f0c0>{number = 3, name = (null)}
2018-04-01 10:22:41.780803+0800 GCD[56160:12471596] 2------>>><NSThread: 0x60400027f0c0>{number = 3, name = (null)}
2018-04-01 10:22:41.781027+0800 GCD[56160:12471596] 3------>>><NSThread: 0x60400027f0c0>{number = 3, name = (null)}

分析:
因?yàn)槭钱惒綀?zhí)行,不會(huì)阻塞當(dāng)前線程,所以先執(zhí)行4,,開(kāi)辟了一條新的線程執(zhí)行1,2,3,然而1,2,3是放到串行隊(duì)列中的,所以依次然順序執(zhí)行1-->2-->3; 這里提一下,既然是異步,為什么不開(kāi)辟多條線程分別執(zhí)行1,2,3,沒(méi)這個(gè)必要,既然已經(jīng)開(kāi)了一天線程,后面的任務(wù)要等前面的執(zhí)行完再執(zhí)行,這個(gè)線程足以讓1,2,3執(zhí)行任務(wù)了,開(kāi)辟線程是消耗資源的;

三. 并發(fā)隊(duì)列 + 同步執(zhí)行

- (void) GCDTest3
{
   
   dispatch_queue_t queue =  dispatch_queue_create("xj", DISPATCH_QUEUE_CONCURRENT);;
   
   dispatch_sync(queue, ^{
       
       NSLog(@"1------>>>%@",[NSThread currentThread]);
       
   });
   
   dispatch_sync(queue, ^{
       
       NSLog(@"2------>>>%@",[NSThread currentThread]);
       
   });
   
   dispatch_sync(queue, ^{
       
       NSLog(@"3------>>>%@",[NSThread currentThread]);
       
   });
   
   NSLog(@"4------>>>%@",[NSThread currentThread]);
}

結(jié)果

2018-04-01 10:30:24.402362+0800 GCD[56597:12479909] 1------>>><NSThread: 0x60400006f580>{number = 1, name = main}
2018-04-01 10:30:24.432775+0800 GCD[56597:12479909] 2------>>><NSThread: 0x60400006f580>{number = 1, name = main}
2018-04-01 10:30:24.439568+0800 GCD[56597:12479909] 3------>>><NSThread: 0x60400006f580>{number = 1, name = main}
2018-04-01 10:30:24.439568+0800 GCD[56160:12471344] 4------>>><NSThread: 0x604000079940>{number = 1, name = main}

分析:由于是同步執(zhí)行,所以不會(huì)另開(kāi)線程,阻塞當(dāng)前線程,所以4是最后執(zhí)行的,雖然是并發(fā)隊(duì)列可以不用等前面的任務(wù)執(zhí)行完,但是就一條線程,不得不等前面的任務(wù)執(zhí)行完才執(zhí)行后面的任務(wù),所以1,2,3依次執(zhí)行;

四. 并發(fā)隊(duì)列 + 異步執(zhí)行

 - (void) GCDTest4
{
    
    dispatch_queue_t queue =  dispatch_queue_create("xj", DISPATCH_QUEUE_CONCURRENT);;
    
    dispatch_async(queue, ^{
        
        NSLog(@"1------>>>%@",[NSThread currentThread]);
        
    });
    
    dispatch_async(queue, ^{
        
        NSLog(@"2------>>>%@",[NSThread currentThread]);
        
    });
    
    dispatch_async(queue, ^{
        
        NSLog(@"3------>>>%@",[NSThread currentThread]);
        
    });
    
    NSLog(@"4------>>>%@",[NSThread currentThread]);
    
}

結(jié)果:

2018-04-01 10:31:14.552817+0800 GCD[56662:12481282] 4------>>><NSThread: 0x604000069640>{number = 1, name = main}
2018-04-01 10:31:14.552818+0800 GCD[56662:12481369] 2------>>><NSThread: 0x6000002742c0>{number = 4, name = (null)}
2018-04-01 10:31:14.552820+0800 GCD[56662:12481372] 3------>>><NSThread: 0x600000274240>{number = 5, name = (null)}
2018-04-01 10:31:14.552838+0800 GCD[56662:12481370] 1------>>><NSThread: 0x604000268a40>{number = 3, name = (null)}

分析:
這是最常用的一種方式,因?yàn)樗钱惒疥?duì)列,所以它是不會(huì)堵塞當(dāng)前線程的,4會(huì)先執(zhí)行,由于是并發(fā)隊(duì)列,前面的任務(wù)開(kāi)始執(zhí)行了,后面的任務(wù)便可以出隊(duì)列,異步執(zhí)行導(dǎo)致為它單獨(dú)開(kāi)辟線程執(zhí)行,所以1,2,3會(huì)在不同的線程中執(zhí)行,如果是1,2,3分別是耗時(shí)的操作,那么它們的執(zhí)行順序?qū)⒉坏枚?隨機(jī);

五. 主隊(duì)列 + 同步執(zhí)行

  • 當(dāng)前線程為主線程:

    - (void)viewDidLoad {
     [super viewDidLoad];
     
      NSLog(@"1------>>>%@",[NSThread currentThread]);
     
     dispatch_sync(dispatch_get_main_queue(), ^{
         
         
         NSLog(@"2------>>>%@",[NSThread currentThread]);
         
         
     });
     
     NSLog(@"3------>>>%@",[NSThread currentThread]);
    

    結(jié)果:打印了1---->>>main后崩潰;

    分析:
    很多博客中把這個(gè)案例都說(shuō)的很好,這里我講下我的理解,首先viewDidLoad本身就是主線程中執(zhí)行的,被放在了主隊(duì)列中,當(dāng)執(zhí)行它的時(shí)候發(fā)現(xiàn),里面有個(gè)同步,必須等block里面的任務(wù)執(zhí)行完才行,也就是必須執(zhí)行2,但是這時(shí)候,2又被放入了主隊(duì)列,主隊(duì)列是串行的,很顯然,在主隊(duì)列中2是排在viewDidload任務(wù)后面的,那么它必須等viewDidload執(zhí)行完才可以去執(zhí)行,然后viewDidload必須等2執(zhí)行完,才算完,,,,這樣陷入死循環(huán),就崩潰了;

  • 當(dāng)前線程為分線程:
- (void) GCDTest5
{
   NSLog(@"1------>>>%@",[NSThread currentThread]);
   
   dispatch_sync(dispatch_get_main_queue(), ^{
       
       
       NSLog(@"2------>>>%@",[NSThread currentThread]);
       
       
   });
   
   NSLog(@"3------>>>%@",[NSThread currentThread]);
   }

結(jié)果:

2018-04-01 10:41:49.864270+0800 GCD[57307:12495333] 1------>>><NSThread: 0x604000664d80>{number = 3, name = (null)}
2018-04-01 10:41:49.868650+0800 GCD[57307:12495215] 2------>>><NSThread: 0x604000261d00>{number = 1, name = main}
2018-04-01 10:41:49.869738+0800 GCD[57307:12495333] 3------>>><NSThread: 0x604000664d80>{number = 3, name = (null)}

分析:
這里不同于上面的點(diǎn)在于,GCDTest5被放在了分線程,那么就好辦了,分線程中執(zhí)行GCDTest5任務(wù)時(shí)遇到同步,就會(huì)一直等,2被放到了主隊(duì)列,那么2會(huì)在所有它前面的主隊(duì)列中的任務(wù)執(zhí)行完后執(zhí)行,執(zhí)行完后分線程中GCDTest5會(huì)繼續(xù)往后執(zhí)行;

六. 主隊(duì)列 + 異步執(zhí)行

- (void) GCDTest6
{
    NSLog(@"1------>>>%@",[NSThread currentThread]);
    
    dispatch_async(dispatch_get_main_queue(), ^{
        
        
        NSLog(@"2------>>>%@",[NSThread currentThread]);
        
        
    });
    
    NSLog(@"3------>>>%@",[NSThread currentThread]);
    
}

結(jié)果:

2018-04-01 10:46:06.757861+0800 GCD[57573:12500988] 1------>>><NSThread: 0x60000007f500>{number = 1, name = main}
2018-04-01 10:46:06.758154+0800 GCD[57573:12500988] 3------>>><NSThread: 0x60000007f500>{number = 1, name = main}
2018-04-01 10:46:06.764103+0800 GCD[57573:12500988] 2------>>><NSThread: 0x60000007f500>{number = 1, name = main}

分析:

這個(gè)沒(méi)什么懸念,主隊(duì)列中的任務(wù)是在主線程中執(zhí)行的,而且主隊(duì)列是串行隊(duì)列;

6舷嗡、線程中的通信方式

7轴猎、使用GCD需要注意的地方

8、GCD中的其他重要函數(shù)

  • 隊(duì)列組
    當(dāng)有多個(gè)異步任務(wù)的時(shí)候,但是我們需要這些任務(wù)都完成的時(shí)候,才執(zhí)行一些操作,由于是異步,我們無(wú)法保證所有任務(wù)的結(jié)果,這時(shí)候就可以用到dispatch_group, 比如說(shuō)我們一個(gè)首頁(yè)界面有好多請(qǐng)求,但是我想等所有請(qǐng)求都有結(jié)果的時(shí)候再顯示,不然顯示不全會(huì)很難看,這時(shí)候我們可以這樣:
dispatch_group_t group = dispatch_group_create();
    
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    
    
    dispatch_group_async(group, queue, ^{
        
        for (int i = 0; i < 3; ++i) {
            [NSThread sleepForTimeInterval:2];              // 模擬耗時(shí)操作
            NSLog(@"1---%@",[NSThread currentThread]);      // 打印當(dāng)前線程
        }
        
    });
   
    dispatch_group_async(group, queue, ^{
        
        for (int i = 0; i < 2; ++i) {
            [NSThread sleepForTimeInterval:2];              // 模擬耗時(shí)操作
            NSLog(@"2---%@",[NSThread currentThread]);      // 打印當(dāng)前線程
        }
        
    });
   
    dispatch_group_notify(group, queue, ^{
        
        NSLog(@"---所有任務(wù)完成了--->>");
        
        
    });
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末进萄,一起剝皮案震驚了整個(gè)濱河市捻脖,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌中鼠,老刑警劉巖可婶,帶你破解...
    沈念sama閱讀 211,290評(píng)論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異援雇,居然都是意外死亡矛渴,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,107評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門(mén)惫搏,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)具温,“玉大人,你說(shuō)我怎么就攤上這事筐赔∠承桑” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 156,872評(píng)論 0 347
  • 文/不壞的土叔 我叫張陵茴丰,是天一觀的道長(zhǎng)达皿。 經(jīng)常有香客問(wèn)我天吓,道長(zhǎng),這世上最難降的妖魔是什么峦椰? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,415評(píng)論 1 283
  • 正文 為了忘掉前任龄寞,我火速辦了婚禮,結(jié)果婚禮上汤功,老公的妹妹穿的比我還像新娘物邑。我一直安慰自己,他們只是感情好冤竹,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,453評(píng)論 6 385
  • 文/花漫 我一把揭開(kāi)白布拂封。 她就那樣靜靜地躺著茬射,像睡著了一般鹦蠕。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上在抛,一...
    開(kāi)封第一講書(shū)人閱讀 49,784評(píng)論 1 290
  • 那天钟病,我揣著相機(jī)與錄音,去河邊找鬼刚梭。 笑死肠阱,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的朴读。 我是一名探鬼主播屹徘,決...
    沈念sama閱讀 38,927評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼衅金!你這毒婦竟也來(lái)了噪伊?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 37,691評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤氮唯,失蹤者是張志新(化名)和其女友劉穎鉴吹,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體惩琉,經(jīng)...
    沈念sama閱讀 44,137評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡豆励,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,472評(píng)論 2 326
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了瞒渠。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片良蒸。...
    茶點(diǎn)故事閱讀 38,622評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖伍玖,靈堂內(nèi)的尸體忽然破棺而出嫩痰,到底是詐尸還是另有隱情,我是刑警寧澤私沮,帶...
    沈念sama閱讀 34,289評(píng)論 4 329
  • 正文 年R本政府宣布始赎,位于F島的核電站和橙,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏造垛。R本人自食惡果不足惜魔招,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,887評(píng)論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望五辽。 院中可真熱鬧办斑,春花似錦、人聲如沸杆逗。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,741評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)罪郊。三九已至蠕蚜,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間悔橄,已是汗流浹背靶累。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,977評(píng)論 1 265
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留癣疟,地道東北人挣柬。 一個(gè)月前我還...
    沈念sama閱讀 46,316評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像睛挚,于是被迫代替她去往敵國(guó)和親邪蛔。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,490評(píng)論 2 348

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