OC的多線程2————GCD

多線程實(shí)現(xiàn)的幾種方案,主要包括pthread附鸽、NSThread、GCD瞒瘸、NSOperation坷备。PS:其中pthread和NSThread需要我們管理線程生命周期,比較麻煩情臭,不是很常用省撑,我們重點(diǎn)關(guān)注GCD和NSOperation赌蔑。This is GCD。

GCD竟秫,Grand Central Dispath是異步執(zhí)行任務(wù)的技術(shù)之一娃惯,開發(fā)者只需要制定執(zhí)行的任務(wù),將任務(wù)放入隊(duì)列中肥败,GCD會(huì)自動(dòng)在系統(tǒng)中創(chuàng)建線程來計(jì)劃執(zhí)行這些任務(wù)趾浅。 偉大的中心調(diào)度器,聽起來就很牛逼了馒稍,功能也是比較強(qiáng)大的皿哨。
我們知道任務(wù)是放在隊(duì)列中執(zhí)行的,設(shè)置好執(zhí)行的順序是并行還是串行纽谒,然后設(shè)置執(zhí)行方式是同步還是異步就好了证膨,剩下的事情就交給系統(tǒng)進(jìn)行處理了」那【系統(tǒng)是怎么處理的呢央勒?這里先留個(gè)扣子】

  1. 創(chuàng)建隊(duì)列(隊(duì)列的名稱采用應(yīng)用ID的方式,即按照FQDN-逆序全域名的方式)
    // 串行隊(duì)列
    dispatch_queue_t serialQueue = dispatch_queue_create("com.silence.gcd.mySerialQueue", DISPATCH_QUEUE_SERIAL);

    // 并行隊(duì)列
    dispatch_queue_t concurrentQueue = dispatch_queue_create("com.silence.gcd.myConcurrentQueue", DISPATCH_QUEUE_CONCURRENT);
  1. 設(shè)置執(zhí)行方式
    // 同步執(zhí)行
    dispatch_sync(serialQueue, ^{
        // 所要執(zhí)行的任務(wù)
        NSLog(@"當(dāng)前線程===》%@",[NSThread currentThread]);
    });
// 打印信息:當(dāng)前線程===》<NSThread: 0x600003e493c0>{number = 1, name = main}
// 可以看出沒有創(chuàng)建新的線程澳化,默認(rèn)在主線程順序執(zhí)行

    // 異步執(zhí)行
    dispatch_async(serialQueue, ^{
        // 所要執(zhí)行的任務(wù)
        NSLog(@"當(dāng)前線程===》%@",[NSThread currentThread]);
    });
// 打印信息:當(dāng)前線程===》<NSThread: 0x600001a49a00>{number = 3, name = (null)}
// 可以看出創(chuàng)建了新的線程订歪,在新的線程中執(zhí)行的任務(wù)

  1. 設(shè)置優(yōu)先級(jí)
    這里就說到全局隊(duì)列的一個(gè)特性,設(shè)置優(yōu)先級(jí)肆捕,我們自己創(chuàng)建的隊(duì)列不可以,那么怎么給我們自己創(chuàng)建的隊(duì)列設(shè)置優(yōu)先級(jí)呢盖高?可以將我們創(chuàng)建的隊(duì)列作為全局隊(duì)列的子隊(duì)列慎陵,然后設(shè)置優(yōu)先級(jí)。PS:使用時(shí)盡量用DISPATCH_QUEUE_PRIORITY_DEFAULT喻奥,而且最好不要用這一特性席纽,會(huì)造成優(yōu)先級(jí)倒置的問題。
    // 獲取全局隊(duì)列,設(shè)置最低的優(yōu)先級(jí)
    dispatch_queue_t globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW,0);

    // 創(chuàng)建我們自己的隊(duì)列
    dispatch_queue_t serialQueue = dispatch_queue_create("com.silence.tongbu.createGlobalQueue", DISPATCH_QUEUE_SERIAL);

    // 將我們的隊(duì)列設(shè)置成為全局隊(duì)列的子隊(duì)列
    dispatch_set_target_queue(serialQueue, globalQueue);

    dispatch_async(serialQueue, ^{
        NSLog(@"任務(wù)1:當(dāng)前線程==》%@",[NSThread currentThread]);
    });
    
    // 設(shè)置最高優(yōu)先級(jí)
    dispatch_queue_t serialQueue2 = dispatch_queue_create("com.silence.tongbu.createGlobalQueue2", DISPATCH_QUEUE_SERIAL);
    dispatch_set_target_queue(serialQueue2, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0));
    
    dispatch_async(serialQueue2, ^{
        NSLog(@"任務(wù)2:當(dāng)前線程==》%@",[NSThread currentThread]);
    });

2019-05-30 11:57:53.972219+0800 同步[13224:1596637] 任務(wù)2:當(dāng)前線程==》<NSThread: 0x6000031ec8c0>{number = 3, name = (null)}
2019-05-30 11:57:53.972237+0800 同步[13224:1596638] 任務(wù)1:當(dāng)前線程==》<NSThread: 0x6000031fed80>{number = 4, name = (null)}

4.延遲執(zhí)行dispatch_after(dispatch_time_t when, dispatch_queue_t queue,dispatch_block_t block);
參數(shù)when延遲多久撞蚕,queue追加到那個(gè)隊(duì)列中润梯,block執(zhí)行什么任務(wù)。

    // 設(shè)置延遲多久執(zhí)行
    dispatch_time_t timeQueue = dispatch_time(DISPATCH_TIME_NOW, 3 * NSEC_PER_SEC);
    
    NSLog(@"我要潛水3秒鐘,waiting...");
    dispatch_after(timeQueue, dispatch_get_main_queue(), ^{
        
        NSLog(@"我來也......^v^");
    });
  1. 隊(duì)列組Queue Group甥厦,解決執(zhí)行多個(gè)并行隊(duì)列任務(wù)時(shí)纺铭,想在全部執(zhí)行結(jié)束后執(zhí)行結(jié)束處理。
    // 隊(duì)列組刀疙,主要是為了想再多個(gè)并行任務(wù)都執(zhí)行完成之后舶赔,執(zhí)行結(jié)束操作
    dispatch_queue_t globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    
    dispatch_group_t queueGroup = dispatch_group_create();
    
    dispatch_sync(globalQueue, ^{
        NSLog(@"task 1");
    });

    
    dispatch_sync(globalQueue, ^{
        NSLog(@"task 2");
    });
    
    // 所有的隊(duì)列任務(wù)都完成之后,執(zhí)行結(jié)束操作
    dispatch_group_notify(queueGroup, globalQueue, ^{
        NSLog(@"ALL tasks are done");
    });

6.信號(hào)量(旗語)Semaphore谦秧,是一種控制可訪問資源的信號(hào)標(biāo)識(shí)竟纳,根據(jù)我們?cè)O(shè)定的信號(hào)計(jì)數(shù)撵溃,系統(tǒng)分配執(zhí)行的線程數(shù)。
如何使用信號(hào)量锥累? 先創(chuàng)建一個(gè)信號(hào)量缘挑,然后等待信號(hào)(線程等待),最后信號(hào)來了桶略,喚醒等待的線程语淘。

1>創(chuàng)建信號(hào)量,參數(shù):信號(hào)計(jì)數(shù)的個(gè)數(shù)
    dispatch_semaphore_t  semaphore = dispatch_semaphore_create(1);

2>等待(減少)信號(hào)
        dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);

3>(增加)信號(hào)來了删性,喚醒等待程序
        dispatch_semaphore_signal(semaphore);

PS:執(zhí)行一個(gè)同步任務(wù)亏娜,只有兩個(gè)2資源,只能創(chuàng)建2個(gè)線程蹬挺,怎么執(zhí)行三個(gè)任務(wù)维贺?

    // 設(shè)置信號(hào)量的數(shù)量為2,同時(shí)只能開啟2個(gè)線程
    dispatch_semaphore_t semaphore = dispatch_semaphore_create(1);
    
    dispatch_queue_t concurrentQueue = dispatch_queue_create("com.silence.gcd.myConcurrentQueue", DISPATCH_QUEUE_CONCURRENT);
    
    dispatch_async(concurrentQueue, ^{
        
        // 等待(減少)信號(hào)量巴帮。  *減少計(jì)數(shù)信號(hào)量溯泣。 如果結(jié)果值小于零,此功能在返回前等待信號(hào)發(fā)生榕茧。
        dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
        
        NSLog(@"Task 1");
        
        // 信號(hào)來了垃沦,可以通行。  *增加計(jì)數(shù)信號(hào)量用押。 如果前一個(gè)值小于零肢簿,此函數(shù)在返回之前喚醒等待線程。
        dispatch_semaphore_signal(semaphore);
    });
    
    dispatch_async(concurrentQueue, ^{
        
        // 等待(減少)信號(hào)
        dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
        
        NSLog(@"Task 2");
        
        // (增加)信號(hào)來了蜻拨,喚醒等待信號(hào)
        dispatch_semaphore_signal(semaphore);
    });
    
    dispatch_async(concurrentQueue, ^{
        
        NSLog(@"Task 3");
    });

// 打印信息
2019-06-03 15:41:11.748542+0800 semaphore[25788:4575492] Task 1
2019-06-03 15:41:11.748603+0800 semaphore[25788:4575494] Task 3
2019-06-03 15:41:11.748680+0800 semaphore[25788:4575493] Task 2

7.使用場景1池充,GCD加載耗時(shí)任務(wù),完成之后返回到主線程

    dispatch_queue_t queue = dispatch_queue_create("com.silence.tongbu.mySerialQueue",DISPATCH_QUEUE_SERIAL);
    
    dispatch_async(queue, ^{
       
        // 耗時(shí)操作缎讼,加載一張圖片
        NSURL *url = [NSURL URLWithString:@"https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1523902227523&di=474686c26c7a7d2b815305dd45f0e046&imgtype=0&src=http%3A%2F%2Fcdnq.duitang.com%2Fuploads%2Fitem%2F201504%2F30%2F20150430125352_aeTLk.jpeg"];
        
        NSData *data = [NSData dataWithContentsOfURL:url];
        
        UIImage *image = [UIImage imageWithData:data];
        
        // 加載完成之后收夸,回到主線程,將圖片顯示出來
        dispatch_async(dispatch_get_main_queue(), ^{
            self.imageView.image = image;
        });
    });

使用場景2血崭,并行隊(duì)列任務(wù)中卧惜,想實(shí)現(xiàn)任務(wù)A和任務(wù)C完成之后,再執(zhí)行任務(wù)B

  • 實(shí)現(xiàn)方式1夹纫,使用柵欄函數(shù)(就像一道柵欄一樣將任務(wù)隔開咽瓷,柵欄函數(shù)之前的任務(wù)完成之后,再執(zhí)行柵欄之后的任務(wù))
    UIImage * (^loadPicTask) (void) = ^(){
        
        // 耗時(shí)操作舰讹,加載一張圖片
        NSURL *url = [NSURL URLWithString:@"https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1523902227523&di=474686c26c7a7d2b815305dd45f0e046&imgtype=0&src=http%3A%2F%2Fcdnq.duitang.com%2Fuploads%2Fitem%2F201504%2F30%2F20150430125352_aeTLk.jpeg"];
        
        NSData *data = [NSData dataWithContentsOfURL:url];
        UIImage *image = [UIImage imageWithData:data];
        
        return image;
    };
    
    // 通過柵欄函數(shù)的方式忱详,先實(shí)現(xiàn)任務(wù)A和任務(wù)C完成之后,再執(zhí)行任務(wù)B
    dispatch_queue_t concurrentQueue = dispatch_queue_create("com.silence.barrier.myConcurrentQueue", DISPATCH_QUEUE_CONCURRENT);
    
    // 任務(wù)A
    dispatch_async(concurrentQueue, ^{
        
        NSLog(@"任務(wù)A:獲取圖片==》%@跺涤,當(dāng)前線程==》%@",loadPicTask(),[NSThread currentThread]);
    });
    
    // 任務(wù)C
    dispatch_async(concurrentQueue, ^{
        
        // 耗時(shí)操作匈睁,加載一張圖片
        NSLog(@"任務(wù)C:獲取圖片==》%@监透,當(dāng)前線程==》%@",loadPicTask(),[NSThread currentThread]);
    });
    
    // 柵欄函數(shù)
    dispatch_barrier_async(concurrentQueue, ^{
        
        // 這里省略了一萬字.......
        NSLog(@"------------------------這是著名的柵欄(函數(shù)),這之前的先執(zhí)行航唆,這之后的后執(zhí)行----------------------------------------");
    });
    
    // 任務(wù)B
    dispatch_async(concurrentQueue, ^{
        
        // 耗時(shí)操作胀蛮,加載一張圖片
        NSLog(@"任務(wù)B:獲取圖片==》%@,當(dāng)前線程==》%@",loadPicTask(),[NSThread currentThread]);
    });

//    打印結(jié)果如下糯钙,情況1
//    任務(wù)C:獲取圖片==》<UIImage: 0x6000019c18f0>, {1200, 1200}粪狼,當(dāng)前線程==》<NSThread: 0x60000278df40>{number = 3, name = (null)}
//    任務(wù)A:獲取圖片==》<UIImage: 0x6000019c5260>, {1200, 1200},當(dāng)前線程==》<NSThread: 0x60000279f440>{number = 4, name = (null)}
//    ------------------------這是著名的柵欄(函數(shù))任岸,這之前的先執(zhí)行再榄,這之后的后執(zhí)行----------------------------------------
//    任務(wù)B:獲取圖片==》<UIImage: 0x6000019cda40>, {1200, 1200},當(dāng)前線程==》<NSThread: 0x60000279f440>{number = 4, name = (null)}
    
//    打印結(jié)果如下享潜,情況2
//    任務(wù)A:獲取圖片==》<UIImage: 0x60000341e3e0>, {1200, 1200}困鸥,當(dāng)前線程==》<NSThread: 0x600000a46740>{number = 3, name = (null)}
//    任務(wù)C:獲取圖片==》<UIImage: 0x60000341e3e0>, {1200, 1200},當(dāng)前線程==》<NSThread: 0x600000a74a00>{number = 4, name = (null)}
//    ------------------------這是著名的柵欄(函數(shù))剑按,這之前的先執(zhí)行疾就,這之后的后執(zhí)行----------------------------------------
//    任務(wù)B:獲取圖片==》<UIImage: 0x60000341e3e0>, {1200, 1200},當(dāng)前線程==》<NSThread: 0x600000a74a00>{number = 4, name = (null)}

//    不管你打印的是那種結(jié)果艺蝴,任務(wù)B總是在任務(wù)A和任務(wù)C之后執(zhí)行猬腰。
  • 實(shí)現(xiàn)方式2,使用信號(hào)量猜敢,通過設(shè)置信號(hào)計(jì)數(shù)為2姑荷,這樣每次只能執(zhí)行2個(gè)任務(wù)(A和C),最后在執(zhí)行任務(wù)B
    
    // 通過信號(hào)量的方式缩擂,先實(shí)現(xiàn)任務(wù)A和任務(wù)C完成之后鼠冕,再執(zhí)行任務(wù)B
    dispatch_queue_t concurrentQueue = dispatch_queue_create("com.silence.barrier.myConcurrentQueue", DISPATCH_QUEUE_CONCURRENT);
    
    dispatch_semaphore_t semaphore = dispatch_semaphore_create(2);
    
    // 任務(wù)A
    dispatch_async(concurrentQueue, ^{
        
        // 等待(減少)信號(hào)
        dispatch_semaphore_wait(semaphore,DISPATCH_TIME_FOREVER);
        
        NSLog(@"任務(wù)A:獲取圖片==》%@,當(dāng)前線程==》%@",loadPicTask(),[NSThread currentThread]);
        
        // (增加)信號(hào)來了撇叁,喚醒等待線程
        dispatch_semaphore_signal(semaphore);
        
    });
    
    // 任務(wù)C
    dispatch_async(concurrentQueue, ^{
        
        dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
        
        // 耗時(shí)操作,加載一張圖片
        NSLog(@"任務(wù)C:獲取圖片==》%@畦贸,當(dāng)前線程==》%@",loadPicTask(),[NSThread currentThread]);
        
        dispatch_semaphore_signal(semaphore);
    });

    // 任務(wù)B
    dispatch_async(concurrentQueue, ^{
        
        dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
        
        // 耗時(shí)操作陨闹,加載一張圖片
        NSLog(@"任務(wù)B:獲取圖片==》%@,當(dāng)前線程==》%@",loadPicTask(),[NSThread currentThread]);
        
        dispatch_semaphore_signal(semaphore);
    });

//    打印結(jié)果如下
2019-06-03 16:16:51.676707+0800 semaphore[26364:4699323] 任務(wù)C:獲取圖片==》<UIImage: 0x60000285e610>, {1200, 1200}薄坏,當(dāng)前線程==》<NSThread: 0x600001632180>{number = 3, name = (null)}
2019-06-03 16:16:51.746762+0800 semaphore[26364:4699325] 任務(wù)A:獲取圖片==》<UIImage: 0x600002840000>, {1200, 1200}趋厉,當(dāng)前線程==》<NSThread: 0x600001631f80>{number = 4, name = (null)}
2019-06-03 16:16:51.936077+0800 semaphore[26364:4699322] 任務(wù)B:獲取圖片==》<UIImage: 0x600002853020>, {1200, 1200},當(dāng)前線程==》<NSThread: 0x60000160de80>{number = 5, name = (null)}
  • 實(shí)現(xiàn)方式3胶坠,使用dispatch_group_t調(diào)度組(隊(duì)列組)方式君账,將任務(wù)A和任務(wù)C放在一個(gè)調(diào)度組中執(zhí)行,任務(wù)B在該調(diào)度組執(zhí)行完成之后執(zhí)行沈善。
    // 通過隊(duì)列組的方式乡数,先實(shí)現(xiàn)任務(wù)A和任務(wù)C完成之后椭蹄,再執(zhí)行任務(wù)B
    dispatch_queue_t concurrentQueue = dispatch_queue_create("com.silence.barrier.myConcurrentQueue", DISPATCH_QUEUE_CONCURRENT);
    
    // 創(chuàng)建隊(duì)列組
    dispatch_group_t queueGroup = dispatch_group_create();
    
    // 任務(wù)A
    dispatch_group_async(queueGroup, concurrentQueue, ^{
        NSLog(@"任務(wù)A:獲取圖片==》%@,當(dāng)前線程==》%@",loadPicTask(),[NSThread currentThread]);
    });
     
    // 任務(wù)C
    dispatch_group_async(queueGroup,concurrentQueue, ^{
        
        NSLog(@"任務(wù)C:獲取圖片==》%@净赴,當(dāng)前線程==》%@",loadPicTask(),[NSThread currentThread]);
    });
    
    // 等收到A,C任務(wù)都執(zhí)行完成之后绳矩,再任務(wù)B
    dispatch_group_notify(queueGroup,concurrentQueue, ^{
        
        NSLog(@"任務(wù)B:獲取圖片==》%@,當(dāng)前線程==》%@",loadPicTask(),[NSThread currentThread]);
    });

關(guān)鍵字和概念可以參考:
OC的多線程1————關(guān)鍵詞 以及 解決方案

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末玖翅,一起剝皮案震驚了整個(gè)濱河市翼馆,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌金度,老刑警劉巖应媚,帶你破解...
    沈念sama閱讀 212,718評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異猜极,居然都是意外死亡中姜,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,683評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門魔吐,熙熙樓的掌柜王于貴愁眉苦臉地迎上來扎筒,“玉大人,你說我怎么就攤上這事酬姆∈茸溃” “怎么了?”我有些...
    開封第一講書人閱讀 158,207評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵辞色,是天一觀的道長骨宠。 經(jīng)常有香客問我,道長相满,這世上最難降的妖魔是什么层亿? 我笑而不...
    開封第一講書人閱讀 56,755評(píng)論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮立美,結(jié)果婚禮上匿又,老公的妹妹穿的比我還像新娘。我一直安慰自己建蹄,他們只是感情好碌更,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,862評(píng)論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著洞慎,像睡著了一般痛单。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上劲腿,一...
    開封第一講書人閱讀 50,050評(píng)論 1 291
  • 那天旭绒,我揣著相機(jī)與錄音,去河邊找鬼。 笑死挥吵,一個(gè)胖子當(dāng)著我的面吹牛重父,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播蔫劣,決...
    沈念sama閱讀 39,136評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼坪郭,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼!你這毒婦竟也來了脉幢?” 一聲冷哼從身側(cè)響起歪沃,我...
    開封第一講書人閱讀 37,882評(píng)論 0 268
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎嫌松,沒想到半個(gè)月后沪曙,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,330評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡萎羔,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,651評(píng)論 2 327
  • 正文 我和宋清朗相戀三年液走,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片贾陷。...
    茶點(diǎn)故事閱讀 38,789評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡缘眶,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出髓废,到底是詐尸還是另有隱情巷懈,我是刑警寧澤,帶...
    沈念sama閱讀 34,477評(píng)論 4 333
  • 正文 年R本政府宣布慌洪,位于F島的核電站顶燕,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏冈爹。R本人自食惡果不足惜涌攻,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,135評(píng)論 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望频伤。 院中可真熱鬧恳谎,春花似錦、人聲如沸憋肖。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,864評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽瞬哼。三九已至婚肆,卻和暖如春租副,著一層夾襖步出監(jiān)牢的瞬間坐慰,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,099評(píng)論 1 267
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留结胀,地道東北人赞咙。 一個(gè)月前我還...
    沈念sama閱讀 46,598評(píng)論 2 362
  • 正文 我出身青樓,卻偏偏與公主長得像糟港,于是被迫代替她去往敵國和親攀操。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,697評(píng)論 2 351

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