JavaSE基礎(chǔ)知識(shí)梳理——多線程并發(fā)

10.1 基本概念

  • 進(jìn)程之間內(nèi)存不共享

  • Java中線程間堆內(nèi)存和方法區(qū)共享放吩,棧內(nèi)存獨(dú)立(很重要)御毅,方法區(qū)只有1塊根欧,堆也只有1塊,椂饲可能有多個(gè)凤粗,主線程對(duì)應(yīng)主棧,在進(jìn)程中創(chuàng)建的變量或?qū)ο蟮囊梦挥跅V薪穸梗还蚕硐蛹稹#ǘ鄠€(gè)進(jìn)程間不共享局部變量)

  • 每個(gè)棧與每個(gè)棧之間之間互不干擾,各自執(zhí)行呆躲,這就是多線程并發(fā)异逐。

  • 堆,棧插掂,方法區(qū)

  • image-20200606002653497.png
  • 線程的生命周期:

    NEW:創(chuàng)建

    RUNNABLE:?jiǎn)?dòng)線程之后灰瞻,被喚醒之后,有被CPU調(diào)度的機(jī)會(huì)

    WAITING:進(jìn)入等待集

    WAITINGTIME:帶阻塞時(shí)間的等待

    RUNNING:運(yùn)行態(tài)

    BLOCKING:阻塞態(tài)

    TERMINATED:死亡態(tài)

  • 線程的運(yùn)行由CPU調(diào)度辅甥,每一次運(yùn)行結(jié)束的位置由程序計(jì)數(shù)器計(jì)算酝润,下一次從上一次斷開(kāi)的位置繼續(xù)。

10.2 創(chuàng)建線程的方法

  • 創(chuàng)建線程的方法有很多種:
  1. extends Thread璃弄,重寫(xiě)run()方法
MyThread t = new MyThread()
  1. implements Runnable要销,重寫(xiě)run()方法。==Runnable只是一個(gè)普通接口==
Runnable r = new MyRunnable();
Thread t = new Thread(r);
  1. implements Callable夏块,重寫(xiě)call方法疏咐。==Callable也只是一個(gè)普通接口==
Callable c = new MyCallable();
//用FutureTask去接收Callable,F(xiàn)utureTask是一個(gè)有返回值的線程脐供,因?yàn)閏all()方法有返回值
FutureTask f = new FutureTask(c);
f.run();
f.get();//get是一個(gè)阻塞性方法凳鬓,會(huì)一直獲取。也可以指定等待時(shí)間
  1. 傳入一個(gè)線程Thread1患民,==Thread類(lèi)實(shí)現(xiàn)了Runnable接口==
Thread t = new Thread(Thread1)
  1. 傳入 FutureTask缩举,==FutureTask實(shí)現(xiàn)了RunnableFuture接口,RunnableFuture繼承至Runnable==
Thread t = new Thread(new FutureTask(new Callable(){重寫(xiě)call()方法}))
  1. 線程池ThreadPoolExecutor匹颤,在后面介紹
  2. 線程組ThreadGroup

10.3 線程的常用方法

  • 開(kāi)啟線程

    //Thread類(lèi)
    void start();
    //FutureTask類(lèi)
    Object run();
    

    注意如果直接調(diào)用run()方法不會(huì)開(kāi)啟線程仅孩。

  • 設(shè)置守護(hù)線程

//守護(hù)線程會(huì)等待到所有用戶(hù)線程結(jié)束后自動(dòng)結(jié)束
void setDeamon(true);
  • 中斷,設(shè)置中斷標(biāo)志
/*設(shè)置中斷標(biāo)志并不會(huì)中斷線程印蓖,如果處于wait,sleep,join等阻塞態(tài)被中斷時(shí)辽慕,會(huì)拋出InterruptedException異常
。在catch到異常之后赦肃,中斷標(biāo)志重置為false*/
void interrupt();
Thread t ;
t.interrupt();
  • 檢測(cè)中斷的兩個(gè)方法
//靜態(tài)方法
Thread.interrupted();//檢測(cè)當(dāng)前線程中斷標(biāo)志位溅蛉,如果為true公浪,則返回true并重置為false。
//實(shí)例方法
void isInterrupted();//檢測(cè)中斷標(biāo)志船侧,不重置
  • 阻塞線程的方法
1.void sleep(long timeMills);//掛起線程持續(xù)timeMills時(shí)間欠气,單位毫秒
2.void wait()
  void wait(long timeMills) //需要先獲取鎖,synchronized镜撩,然后用該鎖執(zhí)行wait()预柒,線程將自己掛起并釋放鎖
3.void join() //將調(diào)用者加到當(dāng)前線程,等待調(diào)用者執(zhí)行完畢袁梗。
  • 喚醒線程宜鸯,使線程重新回到Runnable態(tài)
//喚醒線程也要先獲取鎖,synchronized,并且用和wait相同的鎖去notify
void notify()//隨機(jī)喚醒單個(gè)線程
void notifyAll()//喚醒所有在等待中的線程遮怜,只會(huì)喚醒在調(diào)用notifyAll之前就處于等待的線程淋袖。

==notify造成死鎖的原因分析==

? 假如有消費(fèi)者C1和C2,生產(chǎn)者P1锯梁,C1先拿到鎖适贸,發(fā)現(xiàn)沒(méi)有產(chǎn)品,就wait涝桅,然后釋放鎖拜姿,鎖被P1拿到了,就產(chǎn)品+1冯遂,然后notify蕊肥,然后下一次爭(zhēng)搶鎖,P1搶到了蛤肌,發(fā)現(xiàn)有產(chǎn)品壁却,就wait,然后釋放鎖裸准,鎖被C1或者C2拿到了展东,消費(fèi),然后notify炒俱,釋放鎖盐肃,再一次搶奪鎖時(shí),只有消費(fèi)者搶到了权悟,則它就會(huì)wait砸王,這把鎖只要被消費(fèi)者搶到,因?yàn)闆](méi)有產(chǎn)品峦阁,就只能wait谦铃。就進(jìn)入了死鎖。即只要生產(chǎn)者連續(xù)兩次拿到鎖榔昔,必然會(huì)生產(chǎn)產(chǎn)品驹闰,然后第二次將自己掛起瘪菌,后面只要消費(fèi)者消費(fèi)了之后喚醒的不是生產(chǎn)者,就會(huì)使得所有消費(fèi)者都獲得鎖嘹朗,然后把自己掛起师妙。最終進(jìn)入死鎖。

所以結(jié)論是骡显,所有生產(chǎn)者和消費(fèi)者用notifyAll一定不會(huì)死鎖,因?yàn)檫@樣會(huì)喚醒所有掛起的線程曾掂,不存在忽略了生產(chǎn)者而造成后續(xù)的死鎖惫谤。死鎖產(chǎn)生的根本原因是生產(chǎn)者只喚醒生產(chǎn)者,消費(fèi)者只喚醒消費(fèi)者珠洗,最終生產(chǎn)者都認(rèn)為滿(mǎn)了溜歪,然后掛起;消費(fèi)者消費(fèi)完了许蓖,喚醒別的消費(fèi)者蝴猪,別的消費(fèi)者就會(huì)掛起,直到最先的消費(fèi)者被掛起膊爪。而如果都是用notifyAll自阱,就不分差異的喚醒所有

  • 讓出CPU執(zhí)行權(quán)
void yield();//讓出當(dāng)前的CPU執(zhí)行權(quán),讓CPU重新調(diào)度米酬,有可能再次被調(diào)度到
  • 設(shè)置線程優(yōu)先級(jí)
void setPriority();//默認(rèn)等級(jí)5沛豌,最高10,最低1赃额。優(yōu)先級(jí)越高加派,被調(diào)度到的概率越大

10.4 線程同步

  • 線程同步是解決線程安全問(wèn)題的方法,主要有==synchronized==同步跳芳,==Lock==同步和==CAS非阻塞算法==同步芍锦。CPU效率依次遞增

1、synchronized關(guān)鍵字

  • synchronized作用于方法內(nèi)

    //synchronized(lock)飞盆,lock一般是共享的資源娄琉,雖然用其他唯一的實(shí)例也可以,但是推薦用共享資源
    @override
    public void run(){
        synchronized(lock){
            //do something
        }
    }
    
    • synchronized作用于方法上

      1.實(shí)例方法
      public synchronized void method(){} //此時(shí)的鎖為this吓歇,實(shí)例對(duì)象
      
      2.靜態(tài)方法
      public synchronized static void method(){} //此時(shí)的鎖為類(lèi)鎖车胡,class,它是唯一的
      

2照瘾、volatile關(guān)鍵字

  • volatile只保存內(nèi)存可見(jiàn)性匈棘,它不保證線程安全
  • volatile修飾的變量在發(fā)生變化時(shí),會(huì)及時(shí)通知其它線程析命,重新從主內(nèi)存中取值到工作內(nèi)存主卫。但是因?yàn)関olatile不是原子性操作逃默,因此存在線程安全。
  • image-20200606114713038.png
  • 總線嗅探機(jī)制:線程A修改信息后在匯編指令中會(huì)加Lock前綴簇搅,修改信息通過(guò)總線被線程B嗅探到完域,(因?yàn)閏pu和內(nèi)存的交互通過(guò)I\O總線),此時(shí)B就把原來(lái)內(nèi)存空間的變量變?yōu)闊o(wú)效狀態(tài)瘩将。重新從主內(nèi)存中讀取吟税。
  • volatile不保證線程安全的原因:

因?yàn)榫€程A在引擎從工作內(nèi)存中拿到值之后,讀姿现,改是分步的肠仪,這時(shí)候如果另外一個(gè)線程B已經(jīng)完成了寫(xiě)到主內(nèi)存的操作,假如寫(xiě)入的值為2备典。這時(shí)候線程A會(huì)通過(guò)嗅探機(jī)制异旧,感知到volatile修改的值的變化,會(huì)將自己工作內(nèi)存的變量舍去提佣,置位無(wú)效吮蛹,但是引擎已經(jīng)讀取了值了,并且完成了值的修改拌屏,假如修改為了1潮针。這時(shí)候,引擎就會(huì)assgin倚喂,把值存到工作內(nèi)存然低,然后再寫(xiě)到主內(nèi)存,就會(huì)將原來(lái)主內(nèi)存的值給覆蓋了务唐。

3雳攘、Lock鎖

  • java.util.concurrent.locks包下的Lock是一個(gè)接口,其常用實(shí)現(xiàn)類(lèi)為ReentrantLock枫笛,效率比synchronized高吨灭,更安全
  • Lock鎖也只有釋放了才能被其它線程獲取到。
  • ==ReentrantLock==
//它是一個(gè)獨(dú)占鎖
new ReentrantLock(boolean fair);//fair表示是否公平
    公平:先到先得
    不公平:先到不一定先得刑巧,隨機(jī)喧兄,默認(rèn)是不公平

常用方法:

//ReentrantLock類(lèi)
void lock();//上鎖
void unlock();//釋放鎖

boolean tryLock(long time,TimeUnit timeUnit);//嘗試獲取鎖,成功則返回true啊楚,失敗則在規(guī)定的時(shí)間內(nèi)多次嘗試
Condition newCondition();//獲取Condition對(duì)象吠冤,這個(gè)對(duì)象有await()和signal,signallAll方法,相當(dāng)于wait和notify恭理,notifyAll

//Condition類(lèi)
void await();//相當(dāng)于wait()
void await(int timeMills);//相當(dāng)于wait(int timeMills)
void signal();
void signalAll();

示例:

while (true){
    if (lock.tryLock(2, TimeUnit.SECONDS)){
            lock.lock;
        try {
            System.out.println("我獲取到鎖了");
        }finally {
            lock.unlock();
            break;
        }
    }
}
class TaskQueue {
    private final Lock lock = new ReentrantLock();
    private final Condition condition = lock.newCondition();
    private Queue<String> queue = new LinkedList<>();


    public void addTask(String s) {
        lock.lock();
        try {
            queue.add(s);
            condition.signalAll();
        } finally {
            lock.unlock();
        }
    }


    public String getTask() {
        lock.lock();
        try {
            while (queue.isEmpty()) {
                condition.await();
            }
            return queue.remove();
        } finally {
            lock.unlock();
        }
    }
}
  • ==ReentrantReadWriteLock==

    //讀寫(xiě)鎖拯辙,寫(xiě)的優(yōu)先級(jí)高于讀。
    讀寫(xiě)鎖,多個(gè)線程可以同時(shí)獲得讀鎖涯保,但寫(xiě)鎖是獨(dú)占的诉濒,這樣的好處是提高并發(fā)效率。適用于多個(gè)線程讀夕春,少數(shù)線程寫(xiě)未荒。且沒(méi)有寫(xiě)的情況下,才能讀及志。這是一種悲觀鎖片排。
    讀鎖和寫(xiě)鎖本質(zhì)上是同一個(gè)鎖,只是讀鎖可以共享速侈。所以在讀的過(guò)程中也要加鎖率寡,防止被寫(xiě)占有,導(dǎo)致讀的過(guò)程中數(shù)據(jù)變更引起臟讀
    //示例
    public class Counter {
        private final ReadWriteLock rwlock = new ReentrantReadWriteLock();
        private final Lock rlock = rwlock.readLock();
        private final Lock wlock = rwlock.writeLock();
        private int[] counts = new int[10];
    
    
        public void inc(int index) {
            wlock.lock(); // 加寫(xiě)鎖
            try {
                counts[index] += 1;
            } finally {
                wlock.unlock(); // 釋放寫(xiě)鎖
            }
        }
    
    
        public int[] get() {
            rlock.lock(); // 加讀鎖
            try {
                return Arrays.copyOf(counts, counts.length);
            } finally {
                rlock.unlock(); // 釋放讀鎖
            }
        }
    }
    
    • ==StampledLock==

    這是一種樂(lè)觀鎖锌畸,允許在讀的時(shí)候?qū)懹铝樱阅鼙萊eentrantReadWriteLock高


4靖避、JUC包下的原子類(lèi)

  • Atomic類(lèi)采用的是CAS非阻塞算法潭枣,使用的是Unsafe類(lèi)的compareAndSwap()作為基礎(chǔ)。Unsafe類(lèi)下還有很多其它方法幻捏,參考==《并發(fā)編程之美》==盆犁。

  • CAS是機(jī)器級(jí)別的指令,效率比加鎖的方式高篡九。

  • 并發(fā)包分類(lèi):

    1. 其中LongBinaryOperator中的left就是每次accumulate運(yùn)算后的結(jié)果谐岁,第一次計(jì)算時(shí)是構(gòu)造LongAccumulator時(shí)傳入的identity,right是accumulate傳入的參數(shù)榛臼。
    2. LongAdder和LongAccumulator是相對(duì)于Atomic類(lèi)而言伊佃,它們類(lèi)似ThreadLocal,每個(gè)線程都有一個(gè)自己的復(fù)制變量沛善,不需要再為了競(jìng)爭(zhēng)原子資源而消耗時(shí)間航揉。
    3. 原子類(lèi)和鎖的不同之處在于鎖是阻塞的,只能被一個(gè)線程只有金刁,其它線程都必須阻塞等待帅涂。而原子類(lèi)不會(huì)阻塞線程,只不過(guò)同一時(shí)間只有一個(gè)線程可以操作成功尤蛮。
image-20200606121302916.png

10.5 ThreadLocal和ThreadLocalRandom

1媳友、ThreadLocal類(lèi)

  • ThreadLocal<T>是本地線程變量,它是一個(gè)泛型類(lèi)产捞,可以存儲(chǔ)任意類(lèi)型醇锚。每個(gè)線程都有一個(gè)ThreadLocal的復(fù)制∨髁伲互不影響搂抒。==但是必須先在自己的虛擬機(jī)棧里set這個(gè)值==艇搀。一般定義為==static==,最后要在==finally里清除ThreadLocal==求晶。
  • 常用方法
void set();
Object get();
void remove()清除

2焰雕、ThreadLocalRandom類(lèi)

  • ThreadLocalRandom是多線程下使用的Random隨機(jī)數(shù)類(lèi)。
ThreadLocalRandom.current()//獲取當(dāng)前線程的ThreadLocalRandom對(duì)象芳杏。

10.6 線程池

1矩屁、基本概念

  • 線程池和線程組:

    在main方法中自定義的線程都屬于同一個(gè)線程組,同一個(gè)線程組共享變量爵赵,但是線程組使用較少吝秕。

    線程池的效率高,它降低了創(chuàng)建線程的開(kāi)銷(xiāo)空幻。

  • 線程池的關(guān)系

==主要接口視圖關(guān)系==:

Executor:線程池的頂級(jí)接口

ExecutorService:線程池的真正接口

ScheduledExecutorService:需要執(zhí)行重復(fù)任務(wù)的線程池的接口

ThreadPoolExecutor:ExecutorService的默認(rèn)實(shí)現(xiàn)類(lèi)

ScheduledThreadPooleExecutor:繼承至ThreadPoolExecturo烁峭,實(shí)現(xiàn)ScheduledExecutorService接口

如果要執(zhí)行非重復(fù)任務(wù),就轉(zhuǎn)為ExecutorServiece秕铛,如果要執(zhí)行重復(fù)任務(wù)约郁,就轉(zhuǎn)為ScheduledExecutorService。

image-20200606124629735.png
  • 工具類(lèi)

==Executors==提供一些靜態(tài)工廠但两,用于創(chuàng)建不同類(lèi)型的線程池鬓梅。

  • 線程池的一些參數(shù)

    ==corePoolSize==:核心線程數(shù)量
    ==maximumPooleSize==:最大線程數(shù)量

    ==keepAliveTime==:線程沒(méi)有任務(wù)時(shí),最多保存多長(zhǎng)時(shí)間后會(huì)終止

2谨湘、線程池分類(lèi)

  • ==newCachedThreadPool==
//創(chuàng)建一個(gè)帶有緩沖的線程池绽快,緩沖的意思是可以動(dòng)態(tài)調(diào)整線程池的核心線程數(shù)量,當(dāng)超過(guò)了默認(rèn)大小時(shí)紧阔,就擴(kuò)容坊罢。可以人為指定一個(gè)區(qū)間擅耽。
ExecutorService service = Executors.newCachedThreadPool(); //線程池活孩,無(wú)大小限制
  • ==newFixedThreadPool==
//創(chuàng)建一個(gè)指定大小的線程池
ExecutorService service = Executors.newFixedThreadPool(2);
  • ==newSingleThreadPoolExecutor==
//創(chuàng)建一個(gè)單線程的線程池,線程是串行執(zhí)行任務(wù)
ExecutorService service = Executors.newSingleThreadExecutor()
//單線程的執(zhí)行順序秫筏,先執(zhí)行t1再t2诱鞠,再t3,相當(dāng)于固定大小為1
service.execute(t1);
service.execute(t2);
service.execute(t3);
  • ==newScheduledThreadPool==

    //周期性的執(zhí)行任務(wù)
    ExecutorService service = Executors.newScheduledThreadPool();
    service.schedule(t1,2, TimeUnit.SECONDS);//延遲多久執(zhí)行这敬,只執(zhí)行一次航夺,一次性任務(wù)
    service.scheduleAtFixedRate(t1,1,2,TimeUnit.SECONDS);//任務(wù),第一次執(zhí)行的時(shí)間崔涂,間隔多久執(zhí)行一次阳掐,時(shí)間單位
    service.scheduleWithFixedDelay(t1,1,2,TimeUnit.SECONDS);//任務(wù),第一次執(zhí)行的時(shí)間,間隔多久執(zhí)行一次缭保,時(shí)間單位
    service.shutdown();//關(guān)閉線程池
    
    scheduleAtFixedRate 間隔多久就執(zhí)行一次汛闸,從任務(wù)一開(kāi)始就計(jì)時(shí),不管上一次任務(wù)是否執(zhí)行完畢艺骂。但是如果該任務(wù)的執(zhí)行時(shí)間大于周期诸老,那么后續(xù)任務(wù)可能會(huì)延遲開(kāi)始,但是不會(huì)并發(fā)執(zhí)行
    scheduleWithFixedDelay 間隔多久執(zhí)行一次钳恕,指的是等上一次任務(wù)執(zhí)行完畢别伏,再間隔多久,執(zhí)行
    • 線程池的執(zhí)行任務(wù)方法:

      //submit
      Object submit(Callable<T> callable);//適用于有返回值的線程忧额,雖然也可以接收Runnable厘肮,這是返回的是null,但是為了區(qū)分睦番,最好接收Callable类茂。
      
      //execute
      void execute(Runnable runnable);//執(zhí)行無(wú)返回值的線程
      
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市托嚣,隨后出現(xiàn)的幾起案子巩检,更是在濱河造成了極大的恐慌,老刑警劉巖注益,帶你破解...
    沈念sama閱讀 222,000評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件碴巾,死亡現(xiàn)場(chǎng)離奇詭異溯捆,居然都是意外死亡丑搔,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,745評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門(mén)提揍,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)啤月,“玉大人,你說(shuō)我怎么就攤上這事劳跃』阎伲” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 168,561評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵刨仑,是天一觀的道長(zhǎng)郑诺。 經(jīng)常有香客問(wèn)我,道長(zhǎng)杉武,這世上最難降的妖魔是什么辙诞? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,782評(píng)論 1 298
  • 正文 為了忘掉前任,我火速辦了婚禮轻抱,結(jié)果婚禮上飞涂,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好较店,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,798評(píng)論 6 397
  • 文/花漫 我一把揭開(kāi)白布士八。 她就那樣靜靜地躺著,像睡著了一般梁呈。 火紅的嫁衣襯著肌膚如雪婚度。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 52,394評(píng)論 1 310
  • 那天官卡,我揣著相機(jī)與錄音陕见,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛晴音,可吹牛的內(nèi)容都是我干的撼玄。 我是一名探鬼主播,決...
    沈念sama閱讀 40,952評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼忍坷,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了熔脂?” 一聲冷哼從身側(cè)響起佩研,我...
    開(kāi)封第一講書(shū)人閱讀 39,852評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎霞揉,沒(méi)想到半個(gè)月后旬薯,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,409評(píng)論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡适秩,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,483評(píng)論 3 341
  • 正文 我和宋清朗相戀三年绊序,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片秽荞。...
    茶點(diǎn)故事閱讀 40,615評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡骤公,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出扬跋,到底是詐尸還是另有隱情阶捆,我是刑警寧澤,帶...
    沈念sama閱讀 36,303評(píng)論 5 350
  • 正文 年R本政府宣布钦听,位于F島的核電站洒试,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏朴上。R本人自食惡果不足惜垒棋,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,979評(píng)論 3 334
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望余指。 院中可真熱鬧捕犬,春花似錦跷坝、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,470評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至垢粮,卻和暖如春贴届,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背蜡吧。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,571評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工毫蚓, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人昔善。 一個(gè)月前我還...
    沈念sama閱讀 49,041評(píng)論 3 377
  • 正文 我出身青樓元潘,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親君仆。 傳聞我的和親對(duì)象是個(gè)殘疾皇子翩概,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,630評(píng)論 2 359