Android的線程和線程池

導(dǎo)語(yǔ)

在Android系統(tǒng)己儒,線程主要分為主線程和子線程,主線程處理和界面相關(guān)的事情捆毫,而子線程一般用于執(zhí)行耗時(shí)操作闪湾。頻繁創(chuàng)建銷(xiāo)毀線程不明智,使用線程池是正確的做法绩卤。線程池會(huì)緩存一定數(shù)量的線程途样,通過(guò)線程池就可以避免因?yàn)轭l繁創(chuàng)建和銷(xiāo)毀線程所帶來(lái)的系統(tǒng)開(kāi)銷(xiāo)。AsyncTask底層是線程池濒憋,IntentService/HandlerThread底層是線程何暇。

主要內(nèi)容

  • 主線程和子線程
  • Android中的線程形態(tài)
  • Android線程池

具體內(nèi)容

在Android中,線程的形態(tài)有很多種:

  • AsyncTask封裝了線程池和Handler凛驮。
  • HandlerThread是具有消息循環(huán)的線程裆站,內(nèi)部可以使用handler
  • IntentService是一種Service,內(nèi)部采用HandlerThread來(lái)執(zhí)行任務(wù)黔夭,當(dāng)任務(wù)執(zhí)行完畢后IntentService會(huì)自動(dòng)退出宏胯。由于它是一種Service,所以不容易被系統(tǒng)殺死本姥。

操作系統(tǒng)中肩袍,線程是操作系統(tǒng)調(diào)度的最小單元,同時(shí)線程又是一種受限的系統(tǒng)資源婚惫,其創(chuàng)建和銷(xiāo)毀都會(huì)有相應(yīng)的開(kāi)銷(xiāo)氛赐。同時(shí)當(dāng)系統(tǒng)存在大量線程時(shí)魂爪,系統(tǒng)會(huì)通過(guò)時(shí)間片輪轉(zhuǎn)的方式調(diào)度每個(gè)線程,因此線程不可能做到絕對(duì)的并發(fā)鹰祸,除非線程數(shù)量小于等于CPU的核心數(shù)甫窟。

主線程和子線程

主線程主要處理界面交互邏輯,由于用戶隨時(shí)會(huì)和界面交互蛙婴,所以主線程在任何時(shí)候都需要有較高響應(yīng)速度粗井,則不能執(zhí)行耗時(shí)的任務(wù)。

Android3.0開(kāi)始街图,網(wǎng)絡(luò)訪問(wèn)將會(huì)失敗并拋出NetworkOnMainThreadException這個(gè)異常浇衬,這樣做是為了避免主線程由于被耗時(shí)操作所阻塞從而現(xiàn)ANR現(xiàn)象。

Android中的線程形態(tài)

AsyncTask

AsyncTask是一種輕量級(jí)的異步任務(wù)類(lèi), 他可以在線程池中執(zhí)行后臺(tái)任務(wù), 然后把執(zhí)行的進(jìn)度和最終的結(jié)果傳遞給主線程并在主線程更新UI. 從實(shí)現(xiàn)上來(lái)說(shuō). AsyncTask封裝了Thread和Handler, 通過(guò)AsyncTask可以更加方便地執(zhí)行后臺(tái)任務(wù),但是AsyncTask并不適合進(jìn)行特別耗時(shí)的后臺(tái)任務(wù)餐济,對(duì)于特別耗時(shí)的任務(wù)來(lái)說(shuō), 建議使用線程池耘擂。

AsyncTask就是一個(gè)抽象的泛型類(lèi). 這三個(gè)泛型的意義:

  1. Params:參數(shù)的類(lèi)型
  2. Progress:后臺(tái)任務(wù)的執(zhí)行進(jìn)度的類(lèi)型
  3. Result:后臺(tái)任務(wù)的返回結(jié)果的類(lèi)型

如果不需要傳遞具體的參數(shù), 那么這三個(gè)泛型參數(shù)可以用Void來(lái)代替。

四個(gè)方法:

  • onPreExecute()
    在主線程執(zhí)行絮姆,在異步任務(wù)執(zhí)行之前醉冤,此方法會(huì)被調(diào)用,一般可以用于做一些準(zhǔn)備工作篙悯。
  • doInBackground()
    在線程池中執(zhí)行蚁阳,此方法用于執(zhí)行異步任務(wù),參數(shù)params表示異步任務(wù)的輸入?yún)?shù)鸽照。在此方法中可以通過(guò)publishProgress()方法來(lái)更新任務(wù)的進(jìn)度螺捐,publishProgress()方法會(huì)調(diào)用onProgressUpdate()方法,另外此方法需要返回計(jì)算結(jié)果給onPostExecute()矮燎。
  • onProgressUpdate()
    在主線程執(zhí)行定血,在異步任務(wù)執(zhí)行之后,此方法會(huì)被調(diào)用诞外,其中result參數(shù)是后臺(tái)任務(wù)的返回值澜沟,即doInBackground()的返回值。
  • onPostExecute()
    在主線程執(zhí)行峡谊,在異步任務(wù)執(zhí)行之后倔喂,此方法會(huì)被調(diào)用,其中result參數(shù)是后臺(tái)任務(wù)的返回值靖苇,即doInBackground的返回值。

除了上述的四種方法班缰,還有onCancelled()贤壁,它同樣在主線程執(zhí)行,當(dāng)異步任務(wù)被取消時(shí)埠忘,onCancelled()方法會(huì)被調(diào)用脾拆,這個(gè)時(shí)候onPostExecute()則不會(huì)被調(diào)用馒索。

AsyncTask在使用過(guò)程中有一些條件限制:

  • AsyncTask的類(lèi)必須在主線程被加載,這就意味著第一次訪問(wèn)AsyncTask必須發(fā)生在主線程名船,這個(gè)問(wèn)題不是絕對(duì)绰上,因?yàn)樵贏ndroid 4.1及以上的版本已經(jīng)被系統(tǒng)自動(dòng)完成。在Android 5.0的源碼中渠驼,可以看到ActivityThread#main()會(huì)調(diào)用AsyncTask#init()方法蜈块。
  • AsyncTask的對(duì)象必須在主線程中創(chuàng)建。
  • execute方法必須在UI線程調(diào)用迷扇。
  • 不要在程序中直接調(diào)用onPreExecute()百揭,onPostExecute(),doInBackground和onProgressUpdate()蜓席。
  • 一個(gè)AsyncTask對(duì)象只能執(zhí)行一次器一,即只能調(diào)用一次execute()方法,否則會(huì)報(bào)運(yùn)行時(shí)異常厨内。
  • 在Android 1.6之前祈秕,AsyncTask是串行執(zhí)行任務(wù)的;Android 1.6的時(shí)候AsyncTask開(kāi)始采用線程池里處理并行任務(wù)雏胃;但是Android 3.0開(kāi)始请毛,為了避免AsyncTask帶來(lái)的并發(fā)錯(cuò)誤,AsyncTask又采用了一個(gè)線程來(lái)串行的執(zhí)行任務(wù)丑掺。盡管如此在3.0以后获印,仍然可以通過(guò)AsyncTask#executeOnExecutor()方法來(lái)并行執(zhí)行任務(wù)。
AsyncTask的工作原理

AsyncTask中有兩個(gè)線程池(SerialExecutor和THREAD_POOL_EXECUTOR)和一個(gè)Handler(InternalHandler)街州,其中線程池SerialExecutor用于任務(wù)的排列兼丰,而線程池THREAD_POOL_EXECUTOR用于真正的執(zhí)行任務(wù),而InternalHandler用于將執(zhí)行環(huán)境從線程切換到主線程唆缴,其本質(zhì)仍然是線程的調(diào)用過(guò)程鳍征。

AsyncTask的排隊(duì)過(guò)程:首先系統(tǒng)會(huì)把AsyncTask#Params參數(shù)封裝成FutureTask對(duì)象,F(xiàn)utureTask是一個(gè)并發(fā)類(lèi)面徽,在這里充當(dāng)了Runnable的作用艳丛。接著這個(gè)FutureTask會(huì)交給SerialExecutor#execute()方法去處理。這個(gè)方法首先會(huì)把FutureTask對(duì)象插入到任務(wù)隊(duì)列mTasks中趟紊,如果這個(gè)時(shí)候沒(méi)有正在活動(dòng)AsyncTask任務(wù)氮双,那么就會(huì)調(diào)用SerialExecutor#scheduleNext()方法來(lái)執(zhí)行下一個(gè)AsyncTask任務(wù)。同時(shí)當(dāng)一個(gè)AsyncTask任務(wù)執(zhí)行完后霎匈,AsyncTask會(huì)繼續(xù)執(zhí)行其他任務(wù)直到所有的任務(wù)都執(zhí)行完畢為止戴差,從這一點(diǎn)可以看出,在默認(rèn)情況下铛嘱,AsyncTask是串行執(zhí)行的暖释。

HandlerThread

HandlerThread繼承了Thread袭厂,它是一種可以使用Handler的Thread,它的實(shí)現(xiàn)也很簡(jiǎn)單球匕,就是run方法中通過(guò)Looper.prepare()來(lái)創(chuàng)建消息隊(duì)列纹磺,并通過(guò)Looper.loop()來(lái)開(kāi)啟消息循環(huán),這樣在實(shí)際的使用中就允許在HandlerThread中創(chuàng)建Handler亮曹。

從HandlerThread的實(shí)現(xiàn)來(lái)看橄杨,它和普通的Thread有顯著的不同之處。普通的Thread主要用于在run方法中執(zhí)行一個(gè)耗時(shí)任務(wù)乾忱;而HandlerThread在內(nèi)部創(chuàng)建了消息隊(duì)列讥珍,外界需要通過(guò)Handler的消息方式來(lái)通知HandlerThread執(zhí)行一個(gè)具體的任務(wù)。HandlerThread是一個(gè)很有用的類(lèi)窄瘟,在Android中一個(gè)具體使用場(chǎng)景就是IntentService衷佃。

由于HandlerThread#run()是一個(gè)無(wú)線循環(huán)方法,因此當(dāng)明確不需要再使用HandlerThread時(shí)蹄葱,最好通過(guò)quit()或者quitSafely()方法來(lái)終止線程的執(zhí)行氏义。

IntentService

IntentSercie是一種特殊的Service,繼承了Service并且是抽象類(lèi)图云,任務(wù)執(zhí)行完成后會(huì)自動(dòng)停止惯悠,優(yōu)先級(jí)遠(yuǎn)高于普通線程,適合執(zhí)行一些高優(yōu)先級(jí)的后臺(tái)任務(wù)竣况;IntentService封裝了HandlerThread和Handler

  1. onCreate方法自動(dòng)創(chuàng)建一個(gè)HandlerThread
  2. 用它的Looper構(gòu)造了一個(gè)Handler對(duì)象mServiceHandler克婶,這樣通過(guò)mServiceHandler發(fā)送的消息都會(huì)在HandlerThread執(zhí)行。
  3. IntentServiced的onHandlerIntent方法是一個(gè)抽象方法丹泉,需要在子類(lèi)實(shí)現(xiàn)情萤,onHandlerIntent方法執(zhí)行后,stopSelt(int startId)就會(huì)停止服務(wù)摹恨,如果存在多個(gè)后臺(tái)任務(wù)筋岛,執(zhí)行完最后一個(gè)stopSelf(int startId)才會(huì)停止服務(wù)。

Android線程池

優(yōu)點(diǎn):

  • 重用線程池的線程晒哄,減少線程創(chuàng)建和銷(xiāo)毀帶來(lái)的性能開(kāi)銷(xiāo)睁宰。
  • 控制線程池的最大并發(fā)數(shù),避免大量線程互相搶系統(tǒng)資源導(dǎo)致阻塞寝凌。
  • 提供定時(shí)執(zhí)行和間隔循環(huán)執(zhí)行功能柒傻。

Android中的線程池的概念來(lái)源于Java中的Executor,Executor是一個(gè)接口较木,真正的線程池的實(shí)現(xiàn)為T(mén)hreadPoolExecutor.Android的線程池大部分都是通過(guò)Executor提供的工廠方法創(chuàng)建的诅愚。ThreadPoolExecutor提供了一系列參數(shù)來(lái)配制線程池,通過(guò)不同的參數(shù)可以創(chuàng)建不同的線程池。而從功能的特性來(lái)分的話可以分成四類(lèi)违孝。

ThreadPoolExecutor

ThreadPoolExecutor是線程池的真正實(shí)現(xiàn),它的構(gòu)造方法提供了一系列參數(shù)來(lái)配置線程池泳赋,這些參數(shù)將會(huì)直接影響到線程池的功能特性雌桑。

public ThreadPoolExecutor(int corePoolSize,
                 int maximumPoolSize,
                 long keepAliveTime,
                 TimeUnit unit,
                 BlockingQueue<Runnable> workQueue) {
    this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
    Executors.defaultThreadFactory(), defaultHandler);
}
  • corePoolSize:線程池的核心線程數(shù),默認(rèn)情況下祖今,核心線程會(huì)在線程池中一直存活校坑,即使都處于閑置狀態(tài)。如果將ThreadPoolExecutor#allowCoreThreadTimeOut屬性設(shè)置為true千诬,那么閑置的核心線程在等待新任務(wù)到來(lái)時(shí)會(huì)有超時(shí)的策略耍目,這個(gè)時(shí)間間隔由keepAliveTime屬性來(lái)決定。當(dāng)?shù)却龝r(shí)間超過(guò)了keepAliveTime設(shè)定的值那么核心線程將會(huì)終止徐绑。
  • maximumPoolSize:線程池所能容納的最大線程數(shù)邪驮,當(dāng)活動(dòng)線程數(shù)達(dá)到這個(gè)數(shù)值之后,后續(xù)的任務(wù)將會(huì)被阻塞傲茄。
  • keepAliveTime:非核心線程閑置的超時(shí)時(shí)長(zhǎng)毅访,超過(guò)這個(gè)時(shí)長(zhǎng),非核心線程就會(huì)被回收盘榨。allowCoreThreadTimeOut這個(gè)屬性為true的時(shí)候喻粹,這個(gè)屬性同樣會(huì)作用于核心線程。
  • unit:用于指定keepAliveTime參數(shù)的時(shí)間單位草巡,這是一個(gè)枚舉守呜,常用的有TimeUtil.MILLISECONDS(毫秒),TimeUtil.SECONDS(秒)以及TimeUtil.MINUTES(分)
  • workQueue:線程池中的任務(wù)隊(duì)列山憨,通過(guò)線程池的execute方法提交的Runnable對(duì)象會(huì)存儲(chǔ)在這個(gè)參數(shù)中查乒。
  • threadFactory:線程工廠,為線程池提供創(chuàng)建新線程的功能萍歉。ThreadFactory是一個(gè)接口侣颂。

ThreadPoolExecutor執(zhí)行任務(wù)大致遵循如下規(guī)則:

  1. 如果線程池中的線程數(shù)量未達(dá)到核心線程的數(shù)量,那么會(huì)直接啟動(dòng)一個(gè)核心線程來(lái)執(zhí)行任務(wù)枪孩。
  2. 如果線程池中的線程數(shù)量已經(jīng)達(dá)到或者超過(guò)核心線程的數(shù)量憔晒,那么任務(wù)會(huì)被插入到任務(wù)隊(duì)列中排隊(duì)等待執(zhí)行。
  3. 如果在步驟2中無(wú)法將任務(wù)插入到任務(wù)隊(duì)列中蔑舞,這通常是因?yàn)槿蝿?wù)隊(duì)列已滿拒担,這個(gè)時(shí)候如果線程數(shù)量未達(dá)到線程池的規(guī)定的最大值,那么會(huì)立刻啟動(dòng)一個(gè)非核心線程來(lái)執(zhí)行任務(wù)攻询。
  4. 如果步驟3中的線程數(shù)量已經(jīng)達(dá)到最大值的時(shí)候从撼,那么會(huì)拒絕執(zhí)行此任務(wù),ThreadPoolExecutor會(huì)調(diào)用RejectedExecution方法來(lái)通知調(diào)用者钧栖。

AsyncTask的THREAD_POOL_EXECUTOR線程池配置:

  • 核心線程數(shù)等于CPU核心數(shù)+1低零。
  • 線程池最大線程數(shù)為CPU核心數(shù)的2倍+1婆翔。
  • 核心線程無(wú)超時(shí)機(jī)制,非核心線程的閑置超時(shí)時(shí)間為1秒掏婶。
  • 任務(wù)隊(duì)列容量是128责循。
線程池的分類(lèi)
  • FixedThreadPool
    通過(guò)Executor#newFixedThreadPool()方法來(lái)創(chuàng)建. 它是一種線程數(shù)量固定的線程池, 當(dāng)線程處于空閑狀態(tài)時(shí), 它們并不會(huì)被回收, 除非線程池關(guān)閉了. 當(dāng)所有的線程都處于活動(dòng)狀態(tài)時(shí), 新任務(wù)都會(huì)處于等待狀態(tài), 直到有線程空閑出來(lái). 由于FixedThreadPool只有核心線程并且這些核心線程不會(huì)被回收, 這意味著它能夠更加快速地響應(yīng)外界的請(qǐng)求.

  • CachedThreadPool
    通過(guò)Executor#newCachedThreadPool()方法來(lái)創(chuàng)建. 它是一種線程數(shù)量不定的線程池, 它只有非核心線程, 并且其最大值線程數(shù)為Integer.MAX_VALUE. 這就可以認(rèn)為這個(gè)最大線程數(shù)為任意大了. 當(dāng)線程池中的線程都處于活動(dòng)的時(shí)候, 線程池會(huì)創(chuàng)建新的線程來(lái)處理新任務(wù), 否則就會(huì)利用空閑的線程來(lái)處理新任務(wù). 線程池中的空閑線程都有超時(shí)機(jī)制, 這個(gè)超時(shí)時(shí)長(zhǎng)為60S, 超過(guò)這個(gè)時(shí)間那么空閑線程就會(huì)被回收资柔。
    和FixedThreadPool不同的是, CachedThreadPool的任務(wù)隊(duì)列其實(shí)相當(dāng)于一個(gè)空集合, 這將導(dǎo)致任何任務(wù)都會(huì)立即被執(zhí)行, 因?yàn)樵谶@種場(chǎng)景下SynchronousQueue是無(wú)法插入任務(wù)的. SynchronousQueue是一個(gè)非常特殊的隊(duì)列, 在很多情況下可以把它簡(jiǎn)單理解為一個(gè)無(wú)法存儲(chǔ)元素的隊(duì)列. 在實(shí)際使用中很少使用.這類(lèi)線程比較適合執(zhí)行大量的耗時(shí)較少的任務(wù)。

  • ScheduledThreadPool
    通過(guò)Executor#newScheduledThreadPool()方法來(lái)創(chuàng)建. 它的核心線程數(shù)量是固定的, 而非核心線程數(shù)是沒(méi)有限制的, 并且當(dāng)非核心線程閑置時(shí)會(huì)立刻被回收掉. 這類(lèi)線程池用于執(zhí)行定時(shí)任務(wù)和具有固定周期的重復(fù)任務(wù)。

  • SingleThreadExecutor
    通過(guò)Executor#newSingleThreadPool()方法來(lái)創(chuàng)建. 這類(lèi)線程池內(nèi)部只有一個(gè)核心線程, 它確保所有的任務(wù)都在同一個(gè)線程中按順序執(zhí)行. 這類(lèi)線程池意義在于統(tǒng)一所有的外界任務(wù)到一個(gè)線程中, 這使得在這些任務(wù)之間不需要處理線程同步的問(wèn)題吭敢。

更多內(nèi)容戳這里(整理好的各種文集)

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末耿眉,一起剝皮案震驚了整個(gè)濱河市省咨,隨后出現(xiàn)的幾起案子份殿,更是在濱河造成了極大的恐慌,老刑警劉巖枝秤,帶你破解...
    沈念sama閱讀 216,544評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件醋拧,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡宿百,警方通過(guò)查閱死者的電腦和手機(jī)趁仙,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,430評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)垦页,“玉大人雀费,你說(shuō)我怎么就攤上這事∪福” “怎么了盏袄?”我有些...
    開(kāi)封第一講書(shū)人閱讀 162,764評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)薄啥。 經(jīng)常有香客問(wèn)我辕羽,道長(zhǎng),這世上最難降的妖魔是什么垄惧? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,193評(píng)論 1 292
  • 正文 為了忘掉前任刁愿,我火速辦了婚禮,結(jié)果婚禮上到逊,老公的妹妹穿的比我還像新娘铣口。我一直安慰自己,他們只是感情好觉壶,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,216評(píng)論 6 388
  • 文/花漫 我一把揭開(kāi)白布脑题。 她就那樣靜靜地躺著,像睡著了一般铜靶。 火紅的嫁衣襯著肌膚如雪叔遂。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,182評(píng)論 1 299
  • 那天,我揣著相機(jī)與錄音已艰,去河邊找鬼痊末。 笑死,一個(gè)胖子當(dāng)著我的面吹牛哩掺,可吹牛的內(nèi)容都是我干的舌胶。 我是一名探鬼主播,決...
    沈念sama閱讀 40,063評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼疮丛,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了辆它?” 一聲冷哼從身側(cè)響起誊薄,我...
    開(kāi)封第一講書(shū)人閱讀 38,917評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎锰茉,沒(méi)想到半個(gè)月后呢蔫,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,329評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡飒筑,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,543評(píng)論 2 332
  • 正文 我和宋清朗相戀三年片吊,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片协屡。...
    茶點(diǎn)故事閱讀 39,722評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡俏脊,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出肤晓,到底是詐尸還是另有隱情爷贫,我是刑警寧澤,帶...
    沈念sama閱讀 35,425評(píng)論 5 343
  • 正文 年R本政府宣布补憾,位于F島的核電站漫萄,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏盈匾。R本人自食惡果不足惜腾务,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,019評(píng)論 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望削饵。 院中可真熱鬧岩瘦,春花似錦、人聲如沸葵孤。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,671評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)尤仍。三九已至箫津,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背苏遥。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,825評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工饼拍, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人田炭。 一個(gè)月前我還...
    沈念sama閱讀 47,729評(píng)論 2 368
  • 正文 我出身青樓师抄,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親教硫。 傳聞我的和親對(duì)象是個(gè)殘疾皇子叨吮,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,614評(píng)論 2 353

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

  • 因?yàn)橛眯模艜?huì)讓平淡無(wú)奇的日子變得可愛(ài)瞬矩,讓庸常的生活不那么乏味茶鉴。 2007年10月6日 ...
    殘陽(yáng)物語(yǔ)閱讀 1,303評(píng)論 4 6
  • 《千鐘醉》 四季如歌 文 / 文君 一鐘醉,竹林溪水煙波媚景用,山影云亭日夕暉涵叮。清芬裊裊,幽蘭淡淡伞插,燕兒枝間戲割粮。 二鐘...
    君無(wú)情545閱讀 300評(píng)論 0 2
  • 率土記錄哪家強(qiáng)?簡(jiǎn)書(shū)作者粉仔強(qiáng)媚污! 提示:這個(gè)游戲跟我沒(méi)任何關(guān)系舀瓢,我只是普通玩家、普通消費(fèi)者杠步,而且我的觀點(diǎn)一直都是少...
    粉仔強(qiáng)閱讀 612評(píng)論 0 0
  • 封少艷子閱讀 277評(píng)論 0 1