線程池實(shí)戰(zhàn)

更多精彩請(qǐng)關(guān)注公眾號(hào)xhJaver,京東java工程師和你一起成長(zhǎng)

上一篇我們講了講線程池的基本概念以及幾種常見的線程池匾乓,今天我們來趁熱打鐵模擬下在項(xiàng)目中怎么用這線程池

一、線程池實(shí)戰(zhàn)例子

項(xiàng)目背景:需要查出一百個(gè)用戶的信息恬涧,并且給他們的郵箱發(fā)送郵件,打印出最終結(jié)果

用戶類

public class User {
    private Integer id;
    private String email;

    public User(Integer id, String email) {
        this.id =id;
        this.email =email;
    }

    public String getEmail() {
        return email;
    }
}

任務(wù)類

public class Task implements Callable<String> {
   private Integer id;
   
    public Task(Integer id) {
        this.id = id;
    }

    @Override
    public String call() throws Exception {
        //調(diào)用業(yè)務(wù)方提供的查user的服務(wù)奏夫,id不同薛匪,創(chuàng)建任務(wù)的時(shí)候就傳過來id
        User user = DoSomethingService.queryUser(this.id);
        //調(diào)用業(yè)務(wù)方提供發(fā)送郵件的服務(wù)月匣,email不同
        String result = DoSomethingService.sendUserEmail(user.getEmail());
        return result;
    }
}

提供的服務(wù)類

//業(yè)務(wù)提供的服務(wù)
public  class DoSomethingService {
    //查詢用戶100ms
     public static  User queryUser(Integer id) throws InterruptedException {
         //這里可以調(diào)用查詢user的sql語句
         Thread.sleep(100);
         User u= new User(id,id+"xhJaver.com");
         return u;
     }

     //發(fā)送郵件50ms
    public static String sendUserEmail(String email) throws InterruptedException {
        if (email!=null){
            //這里可以調(diào)用發(fā)送email的語句
            Thread.sleep(50);
            return "發(fā)送成功"+email;
        }else {
            return "發(fā)送失敗";
        }

    }
}

我們?cè)賮肀容^一下單線程情況下和多線程情況下相同的操作差別有多大

public class SingleVSConcurrent {
    public static void main(String[] args) {
     //我們模擬一百個(gè)用戶匈睁,我們查出來這一百個(gè)用戶然后再給他們發(fā)郵件
        long singleStart = System.currentTimeMillis();
        for (int i=0;i<100;i++){
            User user = null;
            try {
                user = DoSomethingService.queryUser(i);
                String s = DoSomethingService.sendUserEmail(user.getEmail());
                System.out.println(s);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        long singleEnd = System.currentTimeMillis();
        System.out.println("單線程共用了"+(singleEnd-singleStart)+"ms");
        System.out.println("-------分割線-----------------分割線-----------------分割線-----------------分割線-----------------分割線----------");
        long concurrentStart = System.currentTimeMillis();
        //構(gòu)建要做的任務(wù)列表,查詢出用戶來并且發(fā)送郵件
        List<Task> tasks = new ArrayList<>();
        for (int i=0;i<100;i++){
            //傳id進(jìn)去構(gòu)造不同的任務(wù)桶错,業(yè)務(wù)中有可能是給你個(gè)list列表
            Task task = new Task(i);
            tasks.add(task);
        }
        //返回任務(wù)執(zhí)行結(jié)果
        List<Future<String>> futures = null;
         //用線程池查詢用戶發(fā)送郵件
        ExecutorService executorService = Executors.newFixedThreadPool(100);
        try {
            //是線程池執(zhí)行提交的批量任務(wù)
            futures = executorService.invokeAll(tasks);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        //關(guān)閉線程池
        executorService.shutdown();

        //存放任務(wù)結(jié)果的集合
        List<String> results = new ArrayList<>();
        //遍歷這個(gè)任務(wù)執(zhí)行結(jié)果
        for (Future<String> result:futures) {
            //如果這個(gè)任務(wù)結(jié)束了
            if (result.isDone()){
                String s = null;
                try {
                    //得到這個(gè)任務(wù)的處理結(jié)果,得不到會(huì)一直阻塞
                    s = result.get();
                } catch (ExecutionException e) {
                    e.printStackTrace();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                //將任務(wù)結(jié)果放進(jìn)任務(wù)結(jié)果集合里面
                results.add(s);
            }
        }
        //遍歷任務(wù)結(jié)果的集合
        for (String s:results) {
            System.out.println(s);
        }
        long concurrentEnd = System.currentTimeMillis();
        System.out.println("多線程共用了"+(concurrentEnd-concurrentStart)+"ms");
    }
}

我們最終會(huì)看到輸出結(jié)果為

發(fā)送成功0xhJaver.com
發(fā)送成功1xhJaver.com
發(fā)送成功2xhJaver.com
發(fā)送成功3xhJaver.com
發(fā)送成功4xhJaver.com
發(fā)送成功5xhJaver.com
發(fā)送成功6xhJaver.com
發(fā)送成功7xhJaver.com
發(fā)送成功8xhJaver.com
發(fā)送成功9xhJaver.com
發(fā)送成功10xhJaver.com
發(fā)送成功11xhJaver.com
發(fā)送成功12xhJaver.com
發(fā)送成功13xhJaver.com
發(fā)送成功14xhJaver.com
發(fā)送成功15xhJaver.com
發(fā)送成功16xhJaver.com
發(fā)送成功17xhJaver.com
發(fā)送成功18xhJaver.com
發(fā)送成功19xhJaver.com
發(fā)送成功20xhJaver.com
發(fā)送成功21xhJaver.com
發(fā)送成功22xhJaver.com
發(fā)送成功23xhJaver.com
發(fā)送成功24xhJaver.com
發(fā)送成功25xhJaver.com
發(fā)送成功26xhJaver.com
發(fā)送成功27xhJaver.com
發(fā)送成功28xhJaver.com
發(fā)送成功29xhJaver.com
發(fā)送成功30xhJaver.com
發(fā)送成功31xhJaver.com
發(fā)送成功32xhJaver.com
發(fā)送成功33xhJaver.com
發(fā)送成功34xhJaver.com
發(fā)送成功35xhJaver.com
發(fā)送成功36xhJaver.com
發(fā)送成功37xhJaver.com
發(fā)送成功38xhJaver.com
發(fā)送成功39xhJaver.com
發(fā)送成功40xhJaver.com
發(fā)送成功41xhJaver.com
發(fā)送成功42xhJaver.com
發(fā)送成功43xhJaver.com
發(fā)送成功44xhJaver.com
發(fā)送成功45xhJaver.com
發(fā)送成功46xhJaver.com
發(fā)送成功47xhJaver.com
發(fā)送成功48xhJaver.com
發(fā)送成功49xhJaver.com
發(fā)送成功50xhJaver.com
發(fā)送成功51xhJaver.com
發(fā)送成功52xhJaver.com
發(fā)送成功53xhJaver.com
發(fā)送成功54xhJaver.com
發(fā)送成功55xhJaver.com
發(fā)送成功56xhJaver.com
發(fā)送成功57xhJaver.com
發(fā)送成功58xhJaver.com
發(fā)送成功59xhJaver.com
發(fā)送成功60xhJaver.com
發(fā)送成功61xhJaver.com
發(fā)送成功62xhJaver.com
發(fā)送成功63xhJaver.com
發(fā)送成功64xhJaver.com
發(fā)送成功65xhJaver.com
發(fā)送成功66xhJaver.com
發(fā)送成功67xhJaver.com
發(fā)送成功68xhJaver.com
發(fā)送成功69xhJaver.com
發(fā)送成功70xhJaver.com
發(fā)送成功71xhJaver.com
發(fā)送成功72xhJaver.com
發(fā)送成功73xhJaver.com
發(fā)送成功74xhJaver.com
發(fā)送成功75xhJaver.com
發(fā)送成功76xhJaver.com
發(fā)送成功77xhJaver.com
發(fā)送成功78xhJaver.com
發(fā)送成功79xhJaver.com
發(fā)送成功80xhJaver.com
發(fā)送成功81xhJaver.com
發(fā)送成功82xhJaver.com
發(fā)送成功83xhJaver.com
發(fā)送成功84xhJaver.com
發(fā)送成功85xhJaver.com
發(fā)送成功86xhJaver.com
發(fā)送成功87xhJaver.com
發(fā)送成功88xhJaver.com
發(fā)送成功89xhJaver.com
發(fā)送成功90xhJaver.com
發(fā)送成功91xhJaver.com
發(fā)送成功92xhJaver.com
發(fā)送成功93xhJaver.com
發(fā)送成功94xhJaver.com
發(fā)送成功95xhJaver.com
發(fā)送成功96xhJaver.com
發(fā)送成功97xhJaver.com
發(fā)送成功98xhJaver.com
發(fā)送成功99xhJaver.com
單線程共用了18404ms
-------分割線-----------------分割線-----------------分割線-----------------分割線-----------------分割線----------
發(fā)送成功0xhJaver.com
發(fā)送成功1xhJaver.com
發(fā)送成功2xhJaver.com
發(fā)送成功3xhJaver.com
發(fā)送成功4xhJaver.com
發(fā)送成功5xhJaver.com
發(fā)送成功6xhJaver.com
發(fā)送成功7xhJaver.com
發(fā)送成功8xhJaver.com
發(fā)送成功9xhJaver.com
發(fā)送成功10xhJaver.com
發(fā)送成功11xhJaver.com
發(fā)送成功12xhJaver.com
發(fā)送成功13xhJaver.com
發(fā)送成功14xhJaver.com
發(fā)送成功15xhJaver.com
發(fā)送成功16xhJaver.com
發(fā)送成功17xhJaver.com
發(fā)送成功18xhJaver.com
發(fā)送成功19xhJaver.com
發(fā)送成功20xhJaver.com
發(fā)送成功21xhJaver.com
發(fā)送成功22xhJaver.com
發(fā)送成功23xhJaver.com
發(fā)送成功24xhJaver.com
發(fā)送成功25xhJaver.com
發(fā)送成功26xhJaver.com
發(fā)送成功27xhJaver.com
發(fā)送成功28xhJaver.com
發(fā)送成功29xhJaver.com
發(fā)送成功30xhJaver.com
發(fā)送成功31xhJaver.com
發(fā)送成功32xhJaver.com
發(fā)送成功33xhJaver.com
發(fā)送成功34xhJaver.com
發(fā)送成功35xhJaver.com
發(fā)送成功36xhJaver.com
發(fā)送成功37xhJaver.com
發(fā)送成功38xhJaver.com
發(fā)送成功39xhJaver.com
發(fā)送成功40xhJaver.com
發(fā)送成功41xhJaver.com
發(fā)送成功42xhJaver.com
發(fā)送成功43xhJaver.com
發(fā)送成功44xhJaver.com
發(fā)送成功45xhJaver.com
發(fā)送成功46xhJaver.com
發(fā)送成功47xhJaver.com
發(fā)送成功48xhJaver.com
發(fā)送成功49xhJaver.com
發(fā)送成功50xhJaver.com
發(fā)送成功51xhJaver.com
發(fā)送成功52xhJaver.com
發(fā)送成功53xhJaver.com
發(fā)送成功54xhJaver.com
發(fā)送成功55xhJaver.com
發(fā)送成功56xhJaver.com
發(fā)送成功57xhJaver.com
發(fā)送成功58xhJaver.com
發(fā)送成功59xhJaver.com
發(fā)送成功60xhJaver.com
發(fā)送成功61xhJaver.com
發(fā)送成功62xhJaver.com
發(fā)送成功63xhJaver.com
發(fā)送成功64xhJaver.com
發(fā)送成功65xhJaver.com
發(fā)送成功66xhJaver.com
發(fā)送成功67xhJaver.com
發(fā)送成功68xhJaver.com
發(fā)送成功69xhJaver.com
發(fā)送成功70xhJaver.com
發(fā)送成功71xhJaver.com
發(fā)送成功72xhJaver.com
發(fā)送成功73xhJaver.com
發(fā)送成功74xhJaver.com
發(fā)送成功75xhJaver.com
發(fā)送成功76xhJaver.com
發(fā)送成功77xhJaver.com
發(fā)送成功78xhJaver.com
發(fā)送成功79xhJaver.com
發(fā)送成功80xhJaver.com
發(fā)送成功81xhJaver.com
發(fā)送成功82xhJaver.com
發(fā)送成功83xhJaver.com
發(fā)送成功84xhJaver.com
發(fā)送成功85xhJaver.com
發(fā)送成功86xhJaver.com
發(fā)送成功87xhJaver.com
發(fā)送成功88xhJaver.com
發(fā)送成功89xhJaver.com
發(fā)送成功90xhJaver.com
發(fā)送成功91xhJaver.com
發(fā)送成功92xhJaver.com
發(fā)送成功93xhJaver.com
發(fā)送成功94xhJaver.com
發(fā)送成功95xhJaver.com
發(fā)送成功96xhJaver.com
發(fā)送成功97xhJaver.com
發(fā)送成功98xhJaver.com
發(fā)送成功99xhJaver.com
多線程共用了233ms

從輸出結(jié)果可以知道 單線程共用18404ms / 150 約等于122 多線程共用233ms /150 約等于1

就相當(dāng)于發(fā)用查詢發(fā)送一個(gè)人的時(shí)間解決了這100個(gè)人的問題胀蛮,具體的線程池核心大小數(shù)量要根據(jù)業(yè)務(wù)方面自己配置設(shè)計(jì)

這里面出現(xiàn)了很多和上一篇不會(huì)吧院刁,就是你把線程池講的這么清楚的?沒有講到的知識(shí)點(diǎn)绰上,感興趣的可以去看一看

二吏砂、例子重點(diǎn)講解

文中注釋也都清晰明了的,我在解釋下幾個(gè)重要的

2.1.創(chuàng)建任務(wù)

自定義任務(wù)類實(shí)現(xiàn)這個(gè)接口并且實(shí)現(xiàn)call方法苗胀,返回值為傳入Callable的類型即可

public class Task implements Callable<String> {
   private Integer id;
   
    public Task(Integer id) {
        this.id = id;
    }

    @Override
    public String call() throws Exception {
        //調(diào)用業(yè)務(wù)方提供的查user的服務(wù)狡刘,id不同享潜,創(chuàng)建任務(wù)的時(shí)候就傳過來id
        User user = DoSomethingService.queryUser(this.id);
        //調(diào)用業(yè)務(wù)方提供發(fā)送郵件的服務(wù),email不同
        String result = DoSomethingService.sendUserEmail(user.getEmail());
        return result;
    }
}

2.2.構(gòu)造的任務(wù)列表

//構(gòu)建要做的任務(wù)列表嗅蔬,查詢出用戶來并且發(fā)送郵件
        List<Task> tasks = new ArrayList<>();
        for (int i=0;i<100;i++){
            //傳id進(jìn)去構(gòu)造不同的任務(wù)剑按,業(yè)務(wù)中有可能是給你個(gè)list列表
            Task task = new Task(i);
            tasks.add(task);
        }

2.3.創(chuàng)建線程池提交任務(wù)列表并且關(guān)閉線程池

 //用線程池查詢用戶發(fā)送郵件
        ExecutorService executorService = Executors.newFixedThreadPool(100);
  //返回任務(wù)執(zhí)行結(jié)果
        List<Future<String>> futures = null;
        try {
            //是線程池執(zhí)行提交的批量任務(wù)
            futures = executorService.invokeAll(tasks);
            
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
           //關(guān)閉線程池
        executorService.shutdown();

注:提交任務(wù)的時(shí)候也可以是submit不過在這樣一次提交一個(gè)任務(wù),要是有任務(wù)列表可以用invokeAll shoutdown和shoutdownNow都可以關(guān)閉線程池澜术。但是又很大的區(qū)別 shoutdown :不會(huì)立刻停止線程池艺蝴,但是會(huì)拒絕處理新來的任務(wù),阻塞隊(duì)列中的任務(wù)等他執(zhí)行完 shoutdownNow:會(huì)立刻停止線程池鸟废,拒絕處理新來的任務(wù)并且打斷正在執(zhí)行的線程猜敢,將阻塞隊(duì)列中的任務(wù)全部清空 總的來說就是shoutdown溫柔一點(diǎn),shoutdownNow粗暴一點(diǎn)

2.3.1線程池提交callable任務(wù)四種方法講解

關(guān)于提交線程池提交callable任務(wù)有以下四種方法

  • invokeAll無時(shí)間參數(shù)
  <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)
        throws InterruptedException;

如果調(diào)沒有異常發(fā)生的話都會(huì)調(diào)用成功 如果有一個(gè)有異常則有異常的調(diào)用失敗盒延,其余成功

  • invokeAll有時(shí)間參數(shù)
<T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks,
                                  long timeout, TimeUnit unit)
        throws InterruptedException;

當(dāng)全部任務(wù)執(zhí)行完后超過指定時(shí)限后缩擂,直接拋出異常

  • invokeAny無時(shí)間參數(shù)
    <T> T invokeAny(Collection<? extends Callable<T>> tasks)
        throws InterruptedException, ExecutionException;

invokeAny將第一個(gè)完成的作為結(jié)果,或者調(diào)用失敗則也立即終止其他所有線程添寺。

  • invokeAny有時(shí)間參數(shù)
 <T> T invokeAny(Collection<? extends Callable<T>> tasks,
                    long timeout, TimeUnit unit)
        throws InterruptedException, ExecutionException, TimeoutException;

若設(shè)置了超時(shí)時(shí)間胯盯,未超時(shí)完成則返回正常結(jié)果,否則報(bào)錯(cuò)

2.4.解析任務(wù)結(jié)果

//存放任務(wù)結(jié)果的集合
        List<String> results = new ArrayList<>();
        //遍歷這個(gè)任務(wù)執(zhí)行結(jié)果
        for (Future<String> result:futures) {
            //如果這個(gè)任務(wù)結(jié)束了
            if (result.isDone()){
                String s = null;
                try {
                    //得到這個(gè)任務(wù)的處理結(jié)果畦贸,得不到會(huì)一直阻塞
                    s = result.get();
                } catch (ExecutionException e) {
                    e.printStackTrace();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                //將任務(wù)結(jié)果放進(jìn)任務(wù)結(jié)果集合里面
                results.add(s);
            }
        } 
        //遍歷任務(wù)結(jié)果的集合
        for (String s:results) {
            System.out.println(s);
        }

三陨闹、future接口方法講解

注:future是個(gè)jdk1.5以后出現(xiàn)的異步任務(wù)接口

public interface Future<V> {
   
   //若此任務(wù)已經(jīng)完成或者被取消或者因?yàn)槠渌虿荒鼙蝗∠麆t取消失敗,
   //如果此任務(wù)還沒有開始或者已經(jīng)開始這個(gè)時(shí)候就由這個(gè)參數(shù)來覺得取消與否
  // 在這個(gè)方法執(zhí)行完后薄坏,isDone,iscancel總是返回true,
  //如果任務(wù)無法取消經(jīng)常是因?yàn)槿蝿?wù)被執(zhí)行完了
    boolean cancel(boolean mayInterruptIfRunning);

  //是否取消成功
    boolean isCancelled();

   //任務(wù)是否完成趋厉,正常結(jié)束取消或者異常,都返回true
    boolean isDone();

  //得到這個(gè)任務(wù)的結(jié)果胶坠,會(huì)一直阻塞到得到結(jié)果
  //如果任務(wù)被取消君账,則拋出CancellationException  異常
  //若任務(wù)有異常,則拋出ExecutionException  異常
  //若任務(wù)被中斷則拋出InterruptedException 異常

    V get() throws InterruptedException, ExecutionException;
    
  //得到這個(gè)任務(wù)的結(jié)果沈善,若超過時(shí)間會(huì)拋異常乡数,除此之外和上面那個(gè)方法一樣
    V get(long timeout, TimeUnit unit)
        throws InterruptedException, ExecutionException, TimeoutException;
}

我們文中的例子用到了 V get()這個(gè),下一篇我打算寫一寫線程池為什么可以做到線程復(fù)用闻牡? 源碼面前净赴,沒有秘密

更多精彩請(qǐng)關(guān)注公眾號(hào)xhJaver,京東java工程師和你一起成長(zhǎng)

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市罩润,隨后出現(xiàn)的幾起案子玖翅,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 210,978評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件金度,死亡現(xiàn)場(chǎng)離奇詭異应媚,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)猜极,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,954評(píng)論 2 384
  • 文/潘曉璐 我一進(jìn)店門中姜,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人跟伏,你說我怎么就攤上這事丢胚。” “怎么了酬姆?”我有些...
    開封第一講書人閱讀 156,623評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵嗜桌,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我辞色,道長(zhǎng)骨宠,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,324評(píng)論 1 282
  • 正文 為了忘掉前任相满,我火速辦了婚禮层亿,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘立美。我一直安慰自己匿又,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,390評(píng)論 5 384
  • 文/花漫 我一把揭開白布建蹄。 她就那樣靜靜地躺著碌更,像睡著了一般。 火紅的嫁衣襯著肌膚如雪洞慎。 梳的紋絲不亂的頭發(fā)上痛单,一...
    開封第一講書人閱讀 49,741評(píng)論 1 289
  • 那天,我揣著相機(jī)與錄音劲腿,去河邊找鬼旭绒。 笑死,一個(gè)胖子當(dāng)著我的面吹牛焦人,可吹牛的內(nèi)容都是我干的挥吵。 我是一名探鬼主播,決...
    沈念sama閱讀 38,892評(píng)論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼花椭,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼忽匈!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起矿辽,我...
    開封第一講書人閱讀 37,655評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤丹允,失蹤者是張志新(化名)和其女友劉穎歪沃,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體嫌松,經(jīng)...
    沈念sama閱讀 44,104評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,451評(píng)論 2 325
  • 正文 我和宋清朗相戀三年奕污,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了萎羔。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,569評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡碳默,死狀恐怖贾陷,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情嘱根,我是刑警寧澤髓废,帶...
    沈念sama閱讀 34,254評(píng)論 4 328
  • 正文 年R本政府宣布,位于F島的核電站该抒,受9級(jí)特大地震影響慌洪,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜凑保,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,834評(píng)論 3 312
  • 文/蒙蒙 一冈爹、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧欧引,春花似錦频伤、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,725評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至婚苹,卻和暖如春岸更,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背租副。 一陣腳步聲響...
    開封第一講書人閱讀 31,950評(píng)論 1 264
  • 我被黑心中介騙來泰國(guó)打工坐慰, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人用僧。 一個(gè)月前我還...
    沈念sama閱讀 46,260評(píng)論 2 360
  • 正文 我出身青樓结胀,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親责循。 傳聞我的和親對(duì)象是個(gè)殘疾皇子糟港,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,446評(píng)論 2 348