多任務(wù)

多任務(wù)

  • 多任務(wù)含義:

    • 生活:一邊聽(tīng)歌,一邊跳舞

    • 電腦:同時(shí)運(yùn)行多個(gè)程序寂恬,如:qq续誉,微信莱没,陌陌初肉,瀏覽器

  • 并發(fā)和并行

    • 并發(fā):任務(wù)數(shù)大于核心數(shù),通過(guò)操作系統(tǒng)調(diào)度算法實(shí)現(xiàn)多個(gè)任務(wù)“同時(shí)”執(zhí)行饰躲,實(shí)際上通過(guò)快速切換任務(wù)牙咏,看上去是一起執(zhí)行的,時(shí)間片輪轉(zhuǎn)方式

    • 并行:任務(wù)數(shù)小于核心數(shù)嘹裂,任務(wù)是真正一起執(zhí)行

  • 進(jìn)程:正在運(yùn)行的一個(gè)程序我們可以說(shuō)是一個(gè)進(jìn)程 妄壶,是系統(tǒng)進(jìn)行資源分配和調(diào)用的獨(dú)立單元,每

    一個(gè)進(jìn)程都有自己獨(dú)立的內(nèi)存空間和系統(tǒng)資源

  • 程序:運(yùn)行的應(yīng)用程序稱之為進(jìn)程寄狼。當(dāng)一個(gè)程序不運(yùn)行的時(shí)候我們稱之為程序丁寄,當(dāng)程序運(yùn)行起來(lái)就是一個(gè)進(jìn)程。通俗的來(lái)說(shuō)不運(yùn)行的時(shí)候就是程序泊愧,運(yùn)行起來(lái)就是進(jìn)程伊磺。程序只有一個(gè),但是進(jìn)程可以有多個(gè)

  • 線程:線程是進(jìn)程中的一條執(zhí)行線路或者流程删咱,程序執(zhí)行的最小單位屑埋,線程是任務(wù)調(diào)度的最小單 位。

    • 由于進(jìn)程是資源擁有者痰滋,創(chuàng)建摘能、撤消與切換存在較大的內(nèi)存開(kāi)銷,因此需要引入輕型進(jìn)程 即線程敲街,進(jìn)程是資源分配的最小單位,線程是 CPU 調(diào)度的最小單位(程序真正執(zhí)行的時(shí)候調(diào) 用的是線程)每一個(gè)進(jìn)程中至少有一個(gè)線程
  • 進(jìn)程和線程的關(guān)系:一個(gè)進(jìn)程中可以有一到多個(gè)線程团搞。一個(gè)線程只屬于一個(gè)進(jìn)程。一個(gè)進(jìn)程中的多個(gè)線程是一種 競(jìng)爭(zhēng)關(guān)系

創(chuàng)建線程

?

import time
import threading
#一邊聽(tīng)歌多艇,一邊下載歌曲
def listen():
    for i in range(1,6):
        print("正在聽(tīng)歌")
        time.sleep(1)

def down_load():
    for i in range(1,6):
        print("正在下載歌曲")
        time.sleep(1)
# down_load()
# listen()

if __name__ == '__main__':
    #創(chuàng)建多線程
    t1 = threading.Thread(target=down_load)
    t2 = threading.Thread(target=listen)
    #開(kāi)啟線程
    t1.start()
    t2.start()
#執(zhí)行順序:程序運(yùn)行時(shí)逻恐,代碼從上向下走,走了if __name__ == '__main__':創(chuàng)建了兩條線程墩蔓,我們稱之為子線程梢莽,程序運(yùn)行時(shí)的線程我們稱之為主線程
#子線程根據(jù)target=xxx,開(kāi)始執(zhí)行指定的函數(shù)
  • 線程注意點(diǎn)

    線程合適開(kāi)啟奸披,何時(shí)結(jié)束
    1.子線程何時(shí)開(kāi)啟昏名,何時(shí)運(yùn)行
      當(dāng)調(diào)用start()時(shí),開(kāi)啟線程阵面,再運(yùn)行線程中的代碼
    2.子線程何時(shí)結(jié)束
      子線程把target指向的函數(shù)中的語(yǔ)句執(zhí)行完畢轻局,當(dāng)前子線程結(jié)束
    3.主線程何時(shí)結(jié)束
      所有子線程執(zhí)行完畢后洪鸭,主線程才結(jié)束
    4.查看線程數(shù)量:threading.enumerate(),可以列出當(dāng)前運(yùn)行的所有線程
    
  • 查看線程執(zhí)行情況

    import threading
    import time
    
    def test1():
        for i in range(1,6):
            time.sleep(1)
            print("--子線程1--%d"%i)
            print("子線程1中查看線程情況",threading.enumerate())
    
    def test2():
        for i in range(1,6):
            time.sleep(1)
            print("--子線程2--%d"%i)
            print("子線程2中查看線程情況",threading.enumerate())
    
    def main():
        print("創(chuàng)建線程之前的線程情況",threading.enumerate())
    
        #創(chuàng)建線程
        t1 = threading.Thread(target=test1)
        t2 = threading.Thread(target=test2)
        time.sleep(0.1)
        print("創(chuàng)建線程之后的線程情況", threading.enumerate())
    
        #開(kāi)啟線程
        t1.start()
        t2.start()
        time.sleep(1)
        print("調(diào)用start之后的線程情況", threading.enumerate())
        time.sleep(6)
        print("等待子線程執(zhí)行結(jié)束后的線程情況", threading.enumerate())
    if __name__ == '__main__':
        main()
    
  • args傳遞參數(shù)

    • 給函數(shù)傳遞參數(shù),使用線程關(guān)鍵字args = ()進(jìn)行傳遞參數(shù)仑扑,傳遞的參數(shù)是一個(gè)元組
    import time
    import threading
    #一邊聽(tīng)歌览爵,一邊下載歌曲
    def listen(num):
        for i in range(1,num):
            print("正在聽(tīng)歌%d"%i)
            time.sleep(1)
    
    def down_load(num):
        for i in range(1,num):
            print("正在下載歌曲%d"%i)
            time.sleep(1)
    
    if __name__ == '__main__':
        #創(chuàng)建多線程
        t1 = threading.Thread(target=down_load,args=(10,))
        t2 = threading.Thread(target=listen,args=(10,))
        #開(kāi)啟線程
        t1.start()
        t2.start()
    
  • join方法

    • 功能:當(dāng)前線程執(zhí)行完后其他線程才會(huì)繼續(xù)執(zhí)行
    def main():
        #創(chuàng)建多線程
        t1 = threading.Thread(target=down_load,args=(5,))
        t2 = threading.Thread(target=listen,args=(5,))
        #開(kāi)啟線程
        t1.start()
        t1.join() #t1執(zhí)行完之后,t2和主線程才會(huì)執(zhí)行結(jié)束
        t2.start()
        # t2.join() #在t1镇饮,t2執(zhí)行完后蜓竹,再繼續(xù)執(zhí)行主線程
    
    if __name__ == '__main__':
        main()
        print("程序執(zhí)行結(jié)束了")
    

setDaemon() 方法

  • setDaemon()將當(dāng)前線程設(shè)置成守護(hù)線程來(lái)守護(hù)主線程:

-當(dāng)主線程結(jié)束后,守護(hù)線程也就結(jié)束储藐,不管是否執(zhí)行完成 俱济,即主線程結(jié)束后不等待子線程,立即結(jié)束

-應(yīng)用場(chǎng)景:qq 多個(gè)聊天窗口钙勃,就是守護(hù)線程

注意:需要在子線程開(kāi)啟的時(shí)候設(shè)置成守護(hù)線程蛛碌,否則無(wú)效

import time
import threading
#一邊聽(tīng)歌,一邊下載歌曲
def listen(num):
    for i in range(1,num):
        print("正在聽(tīng)歌%d"%i)
        time.sleep(1)

def down_load(num):
    for i in range(1,num):
        print("正在下載歌曲%d"%i)
        time.sleep(0.5)
def main():
    #創(chuàng)建多線程
    t1 = threading.Thread(target=down_load,args=(5,))
    t2 = threading.Thread(target=listen,args=(5,))
    # t1.setDaemon(True)
    t2.setDaemon(True)
    #開(kāi)啟線程
    t1.start()
    t2.start()

if __name__ == '__main__':
    main()
    print("程序執(zhí)行結(jié)束了")
  • threading模塊提供的方法

    • threading辖源。currentThread():返回當(dāng)前的線程變量
    • threading.enumerate():可以列出當(dāng)前正在運(yùn)行的所有線程蔚携,正在運(yùn)行的線程:?jiǎn)?dòng)后,結(jié)束前克饶,不包括啟動(dòng)前和終止后
    • threading.activeCount()返回正在運(yùn)行的線程數(shù)量酝蜒,與len(threading.enumerate)有相同的結(jié)果
    • 線程.getName():獲取線程名稱
    • 線程.setName():設(shè)置線程名稱
    • 線程.is_alive():判斷線程存活狀態(tài)
    def listen(num):
        for i in range(1,num):
            print("正在聽(tīng)歌%d"%i)
            time.sleep(1)
    
    def down_load(num):
        for i in range(1,num):
            print("正在下載歌曲%d"%i)
            time.sleep(0.5)
    def main():
        #創(chuàng)建多線程
        t1 = threading.Thread(target=down_load,args=(5,))
        t2 = threading.Thread(target=listen,args=(5,))
        print("t1線程開(kāi)啟之前的狀態(tài)",t1.is_alive()) #False
        t1.setName("黃志")
        print("正在運(yùn)行的線程數(shù)量:",threading.activeCount()) #1
        #開(kāi)啟線程
        t1.start()
        print("當(dāng)前線程:",threading.currentThread()) #MainThread
        print(threading.enumerate())  #列表中2個(gè)線程
        print("正在運(yùn)行的線程數(shù)量:", threading.activeCount()) #2
        t2.start()
        print("當(dāng)前線程:", threading.currentThread()) #MainThread
        print(threading.enumerate()) #列表中3個(gè)線程
        print("正在運(yùn)行的線程數(shù)量:", threading.activeCount()) #3
    
    if __name__ == '__main__':
        main()
        print("程序執(zhí)行結(jié)束了")
        print("正在運(yùn)行的線程數(shù)量:", threading.activeCount()) #3
    

使用繼承方式開(kāi)啟線程

  • 定義一個(gè)類繼承threading.Thread

  • 復(fù)寫(xiě)父類的run方法

    import threading
    import time
    class MyThread(threading.Thread):
        def run(self):
            for i in range(3):
                time.sleep(1)
                msg = f"I'm {self.name} @{i}"
                print(msg)
    def test1():
        for i in range(5):
            #創(chuàng)建線程
            t = MyThread()
            #開(kāi)啟線程
            t.start()
    if __name__ == '__main__':
        test1()
    

線程之間共享全局變量

def work1():
    g_num.append(44)
    print(f"--in work1,g_num is {g_num}") #[11,22,33,44]
def work2():
    print(f"--in work2,g_num is {g_num}") #[11,22,33,44]
t1 = threading.Thread(target=work1)
t2 = threading.Thread(target=work2)
g_num = [11,22,33]
t1.start()
time.sleep(1)
t2.start()
  • 總結(jié):在一個(gè)進(jìn)程內(nèi)的所有線程共享全局變量,很方便在多個(gè)線程共享數(shù)據(jù)
  • 缺點(diǎn):多線程對(duì)全局變量變量隨意修改可能會(huì)造成數(shù)據(jù)混亂(線程非安全)

多線程開(kāi)發(fā)可能會(huì)遇到的問(wèn)題

import time
g_num = 0
def work1(num):
    global g_num
    for i in range(num):
        g_num+=1
    print(f"--in work1,g_num is {g_num}")
def work2(num):
    global g_num
    for i in range(num):
        g_num+=1
    print(f"--in work2,g_num is {g_num}")
t1 = threading.Thread(target=work1,args=(100,))
t2 = threading.Thread(target=work2,args=(100,))
t1.start()
t2.start()
#t1,t2兩個(gè)線程都要對(duì)全局變量g_num進(jìn)行加1運(yùn)算彤路,t1,t2各自對(duì)g_num加100次秕硝,那么最終結(jié)果應(yīng)該是200

#但是由于是多線程同時(shí)操作,可能會(huì)出現(xiàn)以下問(wèn)題
#在g_num=0,t1先取得g_num=0,此時(shí)系統(tǒng)將t1調(diào)為“sleeping”狀態(tài)洲尊,把t2轉(zhuǎn)換成“running”狀態(tài)远豺,t2也獲取g_num=0,
#然后t2對(duì)獲取到的值進(jìn)行加1操作并賦值給g_num,使得g_num=1
#然后系統(tǒng)將將t2調(diào)為“sleeping”狀態(tài),把t1轉(zhuǎn)換成“running”狀態(tài)坞嘀,線程t1把獲取到的g_num=0加1后賦值給g_nun,使得g_num=1
#這樣導(dǎo)致雖然t1和t2都對(duì)g_num加1躯护,但結(jié)果是1

同步和異步

  • 同步:同步就是協(xié)同步調(diào),按預(yù)定的先后次序進(jìn)行運(yùn)行丽涩,同是“協(xié)同”的意思
  • 異步:一個(gè)異步調(diào)用過(guò)程發(fā)出后棺滞,調(diào)用者在沒(méi)得到結(jié)果之前可以進(jìn)行后續(xù)操作。同步和異步是對(duì)應(yīng)的矢渊,兩個(gè)線程要么同步继准,要么異步

互斥鎖

  • 當(dāng)多個(gè)線程幾乎同時(shí)修改一個(gè)共享數(shù)據(jù)的時(shí)候,需要進(jìn)行同步控制矮男,線程同步能夠保證多個(gè) 線程安全的訪問(wèn)競(jìng)爭(zhēng)資源(全局內(nèi)容)移必,最簡(jiǎn)單的同步機(jī)制就是使用互斥鎖

  • 互斥鎖是資源的一個(gè)引用狀態(tài):鎖定/非鎖定

  • 使用過(guò)程:某個(gè)線程要更改 共享數(shù)據(jù)時(shí),先將其鎖定毡鉴,此時(shí)資源的狀態(tài)為鎖定狀態(tài)崔泵,其他線程就不能更改秒赤,直到該線程將 資源狀態(tài)改為非鎖定狀態(tài),也就是釋放資源憎瘸,其他的線程才能再次鎖定資源

    import time
    g_num = 0
    def work1(num):
        global g_num
        for i in range(num):
            mutex.acquire() #鎖定
            g_num+=1
            mutex.release() #釋放
    def work2(num):
        global g_num
        for i in range(num):
            mutex.acquire()  # 鎖定
            g_num += 1
            mutex.release()  # 釋放
    mutex = threading.Lock()
    t1 = threading.Thread(target=work1,args=(1000000,))
    t2 = threading.Thread(target=work2,args=(1000000,))
    t1.start()
    t2.start()
    while len(threading.enumerate())!=1:
        time.sleep(1)
    print(f"--in work2,g_num is {g_num}")
    
    
  • 鎖的好處:

    • 確保了某段關(guān)鍵代碼只能由一個(gè)線程從頭到尾完整地執(zhí)行
  • 鎖的壞處:

    • 阻止了多線程并發(fā)執(zhí)行入篮,包含鎖的某段代碼實(shí)際上只能以單線程模式執(zhí)行,效率就大大地 下降了
    • 由于可以存在多個(gè)鎖幌甘,不同的線程持有不同的鎖潮售,并試圖獲取對(duì)方持有的鎖時(shí),可能會(huì)造成死鎖

死鎖

  • 在多個(gè)線程共享資源的時(shí)候含潘,如果兩個(gè)線程同時(shí)占有一部分資源饲做,并且同時(shí)等待對(duì)方的資源,就會(huì)造成死鎖現(xiàn)象遏弱,盡管死鎖很少發(fā)生,但是一旦發(fā)生就會(huì)造成應(yīng)用程序的停止相應(yīng)

    import time
    def test1():
        #lock1上鎖
        lock1.acquire()
        print("--test1開(kāi)始執(zhí)行--")
        time.sleep(1)
        lock2.acquire()
        print("--test1執(zhí)行結(jié)束--")
        lock2.release() #lock2解鎖
        lock1.release()# lock1解鎖
    
    def test2():
        #lock2上鎖
        lock2.acquire()
        print("--test2開(kāi)始執(zhí)行--")
        # lock1上鎖
        time.sleep(1)
        lock1.acquire()
        print("--test2執(zhí)行結(jié)束--")
        lock1.release()
        lock2.release()
    
    lock1 = threading.Lock()
    lock2 = threading.Lock()
    if __name__ == '__main__':
        t1 = threading.Thread(target=test1)
        t2 = threading.Thread(target=test2)
        t1.start()
        t2.start()
    

生產(chǎn)者和消費(fèi)者

  • 隊(duì)列:Python 的 Queue 模塊中提供了同步的塞弊、線程安全的隊(duì)列類漱逸,包括 FIFO(先入先出)隊(duì)列 Queue, LIFO(后入先出)隊(duì)列 LifoQueue游沿,和優(yōu)先級(jí)隊(duì)列 PriorityQueue饰抒。這些隊(duì)列都實(shí)現(xiàn)了鎖原語(yǔ) (可以理解為原子操作,即要么不做诀黍,要么就做完)袋坑,能夠在多線程中直接使用∶泄矗可以使用 隊(duì)列來(lái)實(shí)現(xiàn)線程間的同步

    from queue import Queue
    q = Queue(maxsize=3)
    q.put("黃志")
    print(q.empty()) #False
    q.put("古印")
    q.put("王濤")
    print(q.full())
    # q.put("楊俊")
    print(q.get())
    print(q.get())
    print(q.get())
    print(q.get())
    # print(q.get(timeout=3))
    # print(q.get_nowait())
    print(q.qsize())
    
  • 生產(chǎn)者和消費(fèi)者

    • 生產(chǎn)者:生成數(shù)據(jù)的線程
    • 消費(fèi)者:處理數(shù)據(jù)的線程
    • 目的:平衡生產(chǎn)者和消費(fèi)者的工作能力來(lái)提高程序的整理處理數(shù)據(jù)的速度
    import time
    import queue
    def producer(name):#生產(chǎn)者
        count = 1
        while True:
            print("%s生產(chǎn)了包子%d"%(name,count))
            q.put(count)
            count+=1
            time.sleep(1)
            print("包子總數(shù):",q.qsize())
    def costom(name):#消費(fèi)者
        while True:
            print("%s吃了包子%s"%(name,q.get()))
            time.sleep(0.5)
    if __name__ == '__main__':
        q = queue.Queue(maxsize=5)
        t1 = threading.Thread(target=producer,args=("黃志",))
        t2 = threading.Thread(target=costom,args=("吃貨古",))
        t3 = threading.Thread(target=costom, args=("吃貨劉",))
        t1.start()
        t2.start()
        t3.start()
    
  • 為什么使用生產(chǎn)者消費(fèi)者模式

    • 在線程世界里枣宫,生產(chǎn)者就是生產(chǎn)數(shù)據(jù)的線程,消費(fèi)者就是消費(fèi)數(shù)據(jù)的線程吃环。在多線程開(kāi)發(fā)當(dāng)

      中也颤,如果生產(chǎn)者處理速度很快,而消費(fèi)者處理速度很慢郁轻,那么生產(chǎn)者就必須等待消費(fèi)者處理

      完翅娶,才能繼續(xù)生產(chǎn)數(shù)據(jù)。同樣的道理好唯,如果消費(fèi)者的處理能力大于生產(chǎn)者竭沫,那么消費(fèi)者就必

      須等待生產(chǎn)者。為了解決這個(gè)問(wèn)題于是引入了生產(chǎn)者和消費(fèi)者模式

  • 什么是生產(chǎn)者消費(fèi)者模式

    • 生產(chǎn)者消費(fèi)者模式是通過(guò)一個(gè)容器來(lái)解決生產(chǎn)者和消費(fèi)者的強(qiáng)耦合問(wèn)題骑篙。生產(chǎn)者和消費(fèi)者彼 此之間不直接通訊蜕提,而通過(guò)阻塞隊(duì)列來(lái)進(jìn)行通訊,所以生產(chǎn)者生產(chǎn)完數(shù)據(jù)之后不用等待消費(fèi)
      者處理替蛉,直接扔給阻塞隊(duì)列贯溅,消費(fèi)者不找生產(chǎn)者要數(shù)據(jù)拄氯,而是直接從阻塞隊(duì)列里取,阻塞隊(duì) 列就相當(dāng)于一個(gè)緩沖區(qū)它浅,平衡了生產(chǎn)者和消費(fèi)者的處理能力
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末译柏,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子姐霍,更是在濱河造成了極大的恐慌鄙麦,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,402評(píng)論 6 499
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件镊折,死亡現(xiàn)場(chǎng)離奇詭異胯府,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)恨胚,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,377評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門(mén)骂因,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人赃泡,你說(shuō)我怎么就攤上這事寒波。” “怎么了升熊?”我有些...
    開(kāi)封第一講書(shū)人閱讀 162,483評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵俄烁,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我级野,道長(zhǎng)页屠,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,165評(píng)論 1 292
  • 正文 為了忘掉前任蓖柔,我火速辦了婚禮辰企,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘渊抽。我一直安慰自己蟆豫,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,176評(píng)論 6 388
  • 文/花漫 我一把揭開(kāi)白布懒闷。 她就那樣靜靜地躺著十减,像睡著了一般。 火紅的嫁衣襯著肌膚如雪愤估。 梳的紋絲不亂的頭發(fā)上帮辟,一...
    開(kāi)封第一講書(shū)人閱讀 51,146評(píng)論 1 297
  • 那天,我揣著相機(jī)與錄音玩焰,去河邊找鬼由驹。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的蔓榄。 我是一名探鬼主播并炮,決...
    沈念sama閱讀 40,032評(píng)論 3 417
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼甥郑!你這毒婦竟也來(lái)了逃魄?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 38,896評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤澜搅,失蹤者是張志新(化名)和其女友劉穎伍俘,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體勉躺,經(jīng)...
    沈念sama閱讀 45,311評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡癌瘾,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,536評(píng)論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了饵溅。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片妨退。...
    茶點(diǎn)故事閱讀 39,696評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖概说,靈堂內(nèi)的尸體忽然破棺而出碧注,到底是詐尸還是另有隱情,我是刑警寧澤糖赔,帶...
    沈念sama閱讀 35,413評(píng)論 5 343
  • 正文 年R本政府宣布,位于F島的核電站轩端,受9級(jí)特大地震影響放典,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜基茵,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,008評(píng)論 3 325
  • 文/蒙蒙 一奋构、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧拱层,春花似錦弥臼、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,659評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至烙肺,卻和暖如春纳猪,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背桃笙。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,815評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工氏堤, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人搏明。 一個(gè)月前我還...
    沈念sama閱讀 47,698評(píng)論 2 368
  • 正文 我出身青樓鼠锈,卻偏偏與公主長(zhǎng)得像闪檬,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子购笆,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,592評(píng)論 2 353