1 多線程的優(yōu)缺點(diǎn)

之前寫的都亂糟糟的材彪,現(xiàn)在也需要重新記憶一遍酱畅。所以重新整理一下JUC包弄喘。

多線程及其優(yōu)缺點(diǎn)

什么是線程

是操作系統(tǒng)能夠進(jìn)行運(yùn)算調(diào)度的最小單位则拷。它被包含在進(jìn)程之中贡蓖,是進(jìn)程中的實(shí)際運(yùn)作單位。(wiki百科)

創(chuàng)建線程的三種方式

public class ThreadTest {
    public static void main(String[] args) throws InterruptedException {
        //1煌茬、繼承Thread方式
        Thread thread1 = new Thread(){
            @Override
            public void run() {
                System.out.println("thread1 start");
            }
        };
        thread1.start();

        //2斥铺、實(shí)現(xiàn)Runnable接口
        Thread thread2 = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("thread2 start");
            }
        });
        thread2.start();

        //3、實(shí)現(xiàn)Callable接口
        ExecutorService executorService = Executors.newSingleThreadExecutor();
        Future<String> future = executorService.submit(new Callable<String>() {
            @Override
            public String call() throws Exception {
                return "future start";
            }
        });
        try {
            String result = future.get();
            System.out.println(result);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }

    }
}

在jdk8之后用lambda表達(dá)式轉(zhuǎn)換一下

public class ThreadTest {
    public static void main(String[] args) throws InterruptedException {
        //1宣旱、繼承Thread方式
        Thread thread1 = new Thread(() -> System.out.println("thread1 start"));
        thread1.start();

        //2仅父、實(shí)現(xiàn)Runnable接口
        Thread thread2 = new Thread(() -> System.out.println("thread2 start"));
        thread2.start();

        //3叛薯、實(shí)現(xiàn)Callable接口
        ExecutorService executorService = Executors.newSingleThreadExecutor();
        Future<String> future = executorService.submit(() -> "future start");
        try {
            String result = future.get();
            System.out.println(result);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }

    }
}

簡(jiǎn)化了一點(diǎn),但是更多是有點(diǎn)懵笙纤,lambda為什么會(huì)簡(jiǎn)化方法耗溜,->是怎么找到對(duì)應(yīng)的方法,下次在研究省容。

為什么要用多線程

早期的CPU是單核的抖拴,為了提升計(jì)算能力,將多個(gè)計(jì)算單元整合到一起腥椒。形成了多核CPU阿宅。多線程就是為了將多核CPU發(fā)揮到極致,一邊提高性能笼蛛。

多線程缺點(diǎn)呢

上面說(shuō)了多線程的有點(diǎn)是:為了提高計(jì)算性能洒放。那么一定會(huì)提高?
答案是不一定的滨砍。有時(shí)候多線程不一定比單線程計(jì)算快往湿。引入《java并發(fā)編程的藝術(shù)》上第一個(gè)例子

public class ConcurrencyTest {

    /** 執(zhí)行次數(shù) */
    private static final long count = 10000l;

    public static void main(String[] args) throws InterruptedException {
        //并發(fā)計(jì)算
        concurrency();
        //單線程計(jì)算
        serial();
    }

    private static void concurrency() throws InterruptedException {
        long start = System.currentTimeMillis();
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                int a = 0;
                for (long i = 0; i < count; i++) {
                    a += 5;
                }
                System.out.println(a);
            }
        });
        thread.start();
        int b = 0;
        for (long i = 0; i < count; i++) {
            b--;
        }
        thread.join();
        long time = System.currentTimeMillis() - start;
        System.out.println("concurrency :" + time + "ms,b=" + b);
    }

    private static void serial() {
        long start = System.currentTimeMillis();
        int a = 0;
        for (long i = 0; i < count; i++) {
            a += 5;
        }
        int b = 0;
        for (long i = 0; i < count; i++) {
            b--;
        }
        long time = System.currentTimeMillis() - start;
        System.out.println("serial:" + time + "ms,b=" + b + ",a=" + a);
    }

}

結(jié)果為

50000
concurrency :22ms,b=-10000
serial:0ms,b=-10000,a=50000

而且多線程會(huì)帶來(lái)額外的開銷

  • 上下文切換
  • 線程安全

上下文切換

時(shí)間片是CPU分配給各個(gè)線程的時(shí)間,因?yàn)闀r(shí)間非常短惋戏,所以CPU不斷通過切換線程领追,讓我們覺得多個(gè)線程是同時(shí)執(zhí)行的,時(shí)間片一般是幾十毫秒响逢。而每次切換時(shí)绒窑,需要保存當(dāng)前的狀態(tài)起來(lái),以便能夠進(jìn)行恢復(fù)先前狀態(tài)舔亭,而這個(gè)切換時(shí)非常損耗性能些膨,過于頻繁反而無(wú)法發(fā)揮出多線程編程的優(yōu)勢(shì)。
減少上下文切換可以采用無(wú)鎖并發(fā)編程钦铺,CAS算法傀蓉,使用最少的線程和使用協(xié)程。

  • 無(wú)鎖并發(fā)編程:可以參照concurrentHashMap鎖分段的思想职抡,不同的線程處理不同段的數(shù)據(jù)葬燎,這樣在多線程競(jìng)爭(zhēng)的條件下,可以減少上下文切換的時(shí)間缚甩。
  • CAS算法谱净,利用Atomic下使用CAS算法來(lái)更新數(shù)據(jù),使用了樂觀鎖擅威,可以有效的減少一部分不必要的鎖競(jìng)爭(zhēng)帶來(lái)的上下文切換
  • 使用最少線程:避免創(chuàng)建不需要的線程壕探,比如任務(wù)很少,但是創(chuàng)建了很多的線程郊丛,這樣會(huì)造成大量的線程都處于等待狀態(tài)
  • 協(xié)程:在單線程里實(shí)現(xiàn)多任務(wù)的調(diào)度李请,并在單線程里維持多個(gè)任務(wù)間的切換

線程安全的問題

多線程編程中最難以把握的就是臨界區(qū)線程安全問題瞧筛,稍微不注意就會(huì)出現(xiàn)死鎖的情況
同樣引入《java并發(fā)編程的藝術(shù)》的一個(gè)例子

public class DeadLockDemo {
    private static String resource_a = "A";
    private static String resource_b = "B";

    public static void main(String[] args) {
        deadLock();
    }

    public static void deadLock() {
        Thread threadA = new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (resource_a) {
                    System.out.println("get resource a");
                    try {
                        Thread.sleep(3000);
                        synchronized (resource_b) {
                            System.out.println("get resource b");
                        }
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        });
        Thread threadB = new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (resource_b) {
                    try {
                        Thread.sleep(3000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("get resource b");
                    synchronized (resource_a) {
                        System.out.println("get resource a");
                    }
                }
            }
        });
        threadA.start();
        threadB.start();

    }
}

然后通過jps查看,找個(gè)這個(gè)類的id
然后通過jstack id來(lái)查看

Found one Java-level deadlock:
=============================
"Thread-1":
  waiting to lock monitor 0x0000000016074808 (object 0x00000000e0b89280, a java.lang.String),
  which is held by "Thread-0"
"Thread-0":
  waiting to lock monitor 0x0000000016075ca8 (object 0x00000000e0b892b0, a java.lang.String),
  which is held by "Thread-1"

Java stack information for the threads listed above:
===================================================


"Thread-1" #11 prio=5 os_prio=0 tid=0x00000000175ba800 nid=0x232c waiting for monitor entry [0x000000001889f000]
   java.lang.Thread.State: BLOCKED (on object monitor)
        at DeadLockDemo$2.run(DeadLockDemo.java:37)
        - waiting to lock <0x00000000e0b89280> (a java.lang.String)
        - locked <0x00000000e0b892b0> (a java.lang.String)
        at java.lang.Thread.run(Thread.java:748)

"Thread-0" #10 prio=5 os_prio=0 tid=0x00000000175b7800 nid=0x234c waiting for monitor entry [0x000000001861f000]
   java.lang.Thread.State: BLOCKED (on object monitor)
        at DeadLockDemo$1.run(DeadLockDemo.java:18)
        - waiting to lock <0x00000000e0b892b0> (a java.lang.String)
        - locked <0x00000000e0b89280> (a java.lang.String)
        at java.lang.Thread.run(Thread.java:748)

兩個(gè)線程相互等待导盅,仔細(xì)看上面的waiting to lock 和locked兩個(gè)對(duì)象较幌。是相互的。造成死鎖白翻。
造成死鎖的原因和解決方案

死鎖:指兩個(gè)或兩個(gè)以上的進(jìn)程在執(zhí)行過程中乍炉,由于競(jìng)爭(zhēng)資源或者由于彼此通信而造成的一種阻塞的現(xiàn)象,若無(wú)外力作用滤馍,它們都將無(wú)法推進(jìn)下去岛琼。
造成死鎖的原因是:

  1. 因?yàn)橄到y(tǒng)資源不足。
  2. 進(jìn)程運(yùn)行推進(jìn)的順序不合適巢株。
  3. 資源分配不當(dāng)?shù)取?/li>

如果系統(tǒng)資源充足槐瑞,進(jìn)程的資源請(qǐng)求都能夠得到滿足,死鎖出現(xiàn)的可能性就很低阁苞,否則
就會(huì)因爭(zhēng)奪有限的資源而陷入死鎖随珠。其次,進(jìn)程運(yùn)行推進(jìn)順序與速度不同猬错,也可能產(chǎn)生死鎖。

那么死鎖的必要條件是:

  1. 互斥條件:一個(gè)資源每次只能被一個(gè)進(jìn)程使用茸歧。
  2. 請(qǐng)求與保持條件:一個(gè)進(jìn)程因請(qǐng)求資源而阻塞時(shí)倦炒,對(duì)已獲得的資源保持不放。
  3. 不剝奪條件:進(jìn)程已獲得的資源软瞎,在末使用完之前逢唤,不能強(qiáng)行剝奪。
  4. 循環(huán)等待條件:若干進(jìn)程之間形成一種頭尾相接的循環(huán)等待資源關(guān)系涤浇。

這四個(gè)條件是 死鎖的必要條件 鳖藕,只要系統(tǒng)發(fā)生死鎖,這些條件必然成立只锭,而只要上述條件之
一不滿足著恩,就不會(huì)發(fā)生死鎖。

線程的狀態(tài)

線程有6種狀態(tài)

  1. NEW:新建,線程被構(gòu)建蜻展,但是還沒有start()
  2. RUNNABLE:運(yùn)行喉誊,java中將就緒和運(yùn)行統(tǒng)稱為運(yùn)行中
  3. BLOCKED:阻塞,線程阻塞于鎖
  4. WAITING:等待纵顾,表示線程進(jìn)入等待狀態(tài)伍茄,需要其他線程的特定動(dòng)作(通知或中斷)
  5. TIMED_WAITING:帶超時(shí)的等待,可以在指定的時(shí)間內(nèi)自動(dòng)返還
  6. TERMINATED:終止施逾,表示線程已經(jīng)執(zhí)行完畢

狀態(tài)轉(zhuǎn)換

線程創(chuàng)建之后調(diào)用start()方法開始運(yùn)行敷矫。
當(dāng)調(diào)用wait(),join(),LockSupport.lock()方法線程會(huì)進(jìn)入到WAITING狀態(tài)例获,而同樣的wait(long timeout)sleep(long), join(long), LockSupport.parkNanos(), LockSupport.parkUtil()增加了超時(shí)等待的功能曹仗,也就是調(diào)用這些方法后線程會(huì)進(jìn)入TIMED_WAITING狀態(tài)榨汤,當(dāng)超時(shí)等待時(shí)間到達(dá)后,線程會(huì)切換到Runable的狀態(tài)整葡,另外當(dāng)WAITINGTIMED _WAITING狀態(tài)時(shí)可以通過Object.notify(),Object.notifyAll()方法使線程轉(zhuǎn)換到Runable狀態(tài)件余。當(dāng)線程出現(xiàn)資源競(jìng)爭(zhēng)時(shí),即等待獲取鎖的時(shí)候遭居,線程會(huì)進(jìn)入到BLOCKED阻塞狀態(tài)啼器,當(dāng)線程獲取鎖時(shí),線程進(jìn)入到Runable狀態(tài)俱萍。線程運(yùn)行結(jié)束后端壳,線程進(jìn)入到TERMINATED狀態(tài),狀態(tài)轉(zhuǎn)換可以說(shuō)是線程的生命周期枪蘑。
注意
當(dāng)線程進(jìn)入到synchronized方法或者synchronized代碼塊時(shí)损谦,線程切換到的是BLOCKED狀態(tài).
而使用java.util.concurrent.lockslock進(jìn)行加鎖的時(shí)候線程切換的是WAITING或者TIMED_WAITING狀態(tài),因?yàn)閘ock會(huì)調(diào)用LockSupport的方法岳颇。

線程狀態(tài)的操作

interrupted()

中斷可以理解為線程的一個(gè)標(biāo)志位照捡,它表示了一個(gè)運(yùn)行中的線程是否被其他線程進(jìn)行了中斷操作。中斷好比其他線程對(duì)該線程打了一個(gè)招呼话侧。
其他線程可以調(diào)用該線程的interrupt()方法對(duì)其進(jìn)行中斷操作栗精,同時(shí)該線程可以調(diào)用 isInterrupted()來(lái)感知其他線程對(duì)其自身的中斷操作,從而做出響應(yīng)瞻鹏。
另外悲立,同樣可以調(diào)用Thread的靜態(tài)方法 interrupted()對(duì)當(dāng)前線程進(jìn)行中斷操作,該方法會(huì)清除中斷標(biāo)志位新博。

public class InterruptDemo {
    public static void main(String[] args) throws InterruptedException {
        //sleepThread睡眠1000ms
        final Thread sleepThread = new Thread() {
            @Override
            public void run() {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                super.run();
            }
        };
        //busyThread一直執(zhí)行死循環(huán)
        Thread busyThread = new Thread() {
            @Override
            public void run() {
                while (true) ;
            }
        };
        sleepThread.start();
        busyThread.start();
        sleepThread.interrupt();
        busyThread.interrupt();
        while (sleepThread.isInterrupted()) ;
        System.out.println("sleepThread isInterrupted: " + sleepThread.isInterrupted());
        System.out.println("busyThread isInterrupted: " + busyThread.isInterrupted());
    }
}

運(yùn)行結(jié)果是:


對(duì)著兩個(gè)線程進(jìn)行中斷操作薪夕,可以看出sleepThread拋出InterruptedException后清除標(biāo)志位,而busyThread就不會(huì)清除標(biāo)志位赫悄。

join()

join方法可以看做是線程間協(xié)作的一種方式原献。
如果一個(gè)線程實(shí)例A執(zhí)行了threadB.join(),其含義是:當(dāng)前線程A會(huì)等待threadB線程終止后threadA才會(huì)繼續(xù)執(zhí)行。

public class JoinDemo {
    public static void main(String[] args) {
        Thread previousThread = Thread.currentThread();
        for (int i = 1; i <= 5; i++) {
            Thread curThread = new JoinThread(previousThread);
            curThread.start();
            previousThread = curThread;
        }
    }

    static class JoinThread extends Thread {
        private Thread thread;

        public JoinThread(Thread thread) {
            this.thread = thread;
        }

        @Override
        public void run() {
            try {
               //join
               thread.join();
                System.out.println(thread.getName() + " terminated.");
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}
運(yùn)行結(jié)果

如果注釋了上面的thread.join();

運(yùn)行結(jié)果

每個(gè)線程都會(huì)等待前一個(gè)線程結(jié)束才會(huì)繼續(xù)運(yùn)行埂淮。

sleep() VS wait()

兩者主要的區(qū)別:

  1. sleep()方法是Thread的靜態(tài)方法嚼贡,而wait是Object實(shí)例方法
  2. wait()方法必須要在同步方法或者同步塊中調(diào)用,也就是必須已經(jīng)獲得對(duì)象鎖同诫。而sleep()方法沒有這個(gè)限制可以在任何地方種使用粤策。另外,wait()方法會(huì)釋放占有的對(duì)象鎖误窖,使得該線程進(jìn)入等待池中叮盘,等待下一次獲取資源秩贰。而sleep()方法只是會(huì)讓出CPU并不會(huì)釋放掉對(duì)象鎖;
  3. sleep()方法在休眠時(shí)間達(dá)到后如果再次獲得CPU時(shí)間片就會(huì)繼續(xù)執(zhí)行柔吼,而wait()方法必須等待Object.notift/Object.notifyAll通知后毒费,才會(huì)離開等待池,并且再次獲得CPU時(shí)間片才會(huì)繼續(xù)執(zhí)行愈魏。

守護(hù)線程Daemon

守護(hù)線程是一種特殊的線程觅玻,就和它的名字一樣,它是系統(tǒng)的守護(hù)者培漏,在后臺(tái)默默地守護(hù)一些系統(tǒng)服務(wù)溪厘,比如垃圾回收線程,JIT線程就可以理解守護(hù)線程牌柄。與之對(duì)應(yīng)的就是用戶線程畸悬,用戶線程就可以認(rèn)為是系統(tǒng)的工作線程,它會(huì)完成整個(gè)系統(tǒng)的業(yè)務(wù)操作珊佣。用戶線程完全結(jié)束后就意味著整個(gè)系統(tǒng)的業(yè)務(wù)任務(wù)全部結(jié)束了蹋宦,因此系統(tǒng)就沒有對(duì)象需要守護(hù)的了,守護(hù)線程自然而然就會(huì)退咒锻。當(dāng)一個(gè)Java應(yīng)用冷冗,只有守護(hù)線程的時(shí)候,虛擬機(jī)就會(huì)自然退出惑艇。下面以一個(gè)簡(jiǎn)單的例子來(lái)表述Daemon線程的使用蒿辙。

public class DaemonDemo {
    public static void main(String[] args) {
        Thread daemonThread = new Thread(new Runnable() {
            @Override
            public void run() {
                while (true) {
                    try {
                        System.out.println("i am alive");
                        Thread.sleep(500);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    } finally {
                        System.out.println("finally block");
                    }
                }
            }
        });
        //設(shè)置為守護(hù)線程
        daemonThread.setDaemon(true);
        daemonThread.start();
        //確保main線程結(jié)束前能給daemonThread能夠分到時(shí)間片
        try {
            Thread.sleep(800);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

運(yùn)行結(jié)果:

結(jié)果

守護(hù)線程應(yīng)該先于start()方法之前。如果在之后敦捧,但是該線程還是會(huì)執(zhí)行,只不過會(huì)當(dāng)做正常的用戶線程執(zhí)行碰镜。

其他的一些概念

同步和異步

同步和異步通常用來(lái)形容一次方法調(diào)用兢卵。
同步方法調(diào)用一開始,調(diào)用者必須等待被調(diào)用的方法結(jié)束后绪颖,調(diào)用者后面的代碼才能執(zhí)行秽荤。
而異步調(diào)用,指的是柠横,調(diào)用者不用管被調(diào)用方法是否完成窃款,都會(huì)繼續(xù)執(zhí)行后面的代碼,當(dāng)被調(diào)用的方法完成后會(huì)通知調(diào)用者牍氛。

并發(fā)與并行

并發(fā)指的是多個(gè)任務(wù)交替進(jìn)行晨继,而并行則是指真正意義上的“同時(shí)進(jìn)行”。
實(shí)際上搬俊,如果系統(tǒng)內(nèi)只有一個(gè)CPU紊扬,而使用多線程時(shí)蜒茄,那么真實(shí)系統(tǒng)環(huán)境下不能并行,只能通過切換時(shí)間片的方式交替進(jìn)行餐屎,而成為并發(fā)執(zhí)行任務(wù)檀葛。真正的并行也只能出現(xiàn)在擁有多個(gè)CPU的系統(tǒng)中。

阻塞和非阻塞

阻塞和非阻塞通常用來(lái)形容多線程間的相互影響腹缩。
比如一個(gè)線程占有了臨界區(qū)資源屿聋,那么其他線程需要這個(gè)資源就必須進(jìn)行等待該資源的釋放,會(huì)導(dǎo)致等待的線程掛起藏鹊,這種情況就是阻塞润讥。
而非阻塞就恰好相反,它強(qiáng)調(diào)沒有一個(gè)線程可以阻塞其他線程伙判,所有的線程都會(huì)嘗試地往前運(yùn)行象对。

臨界區(qū)

臨界區(qū)用來(lái)表示一種公共資源或者說(shuō)是共享數(shù)據(jù),可以被多個(gè)線程使用宴抚。但是每個(gè)線程使用時(shí)企锌,一旦臨界區(qū)資源被一個(gè)線程占有,那么其他線程必須等待来颤。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末码党,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子常潮,更是在濱河造成了極大的恐慌弟胀,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,816評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件喊式,死亡現(xiàn)場(chǎng)離奇詭異孵户,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)岔留,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,729評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門夏哭,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人献联,你說(shuō)我怎么就攤上這事竖配。” “怎么了里逆?”我有些...
    開封第一講書人閱讀 158,300評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵进胯,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我原押,道長(zhǎng)胁镐,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,780評(píng)論 1 285
  • 正文 為了忘掉前任,我火速辦了婚禮希停,結(jié)果婚禮上烁巫,老公的妹妹穿的比我還像新娘。我一直安慰自己宠能,他們只是感情好亚隙,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,890評(píng)論 6 385
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著违崇,像睡著了一般阿弃。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上羞延,一...
    開封第一講書人閱讀 50,084評(píng)論 1 291
  • 那天渣淳,我揣著相機(jī)與錄音,去河邊找鬼伴箩。 笑死入愧,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的嗤谚。 我是一名探鬼主播棺蛛,決...
    沈念sama閱讀 39,151評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼巩步!你這毒婦竟也來(lái)了旁赊?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,912評(píng)論 0 268
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤椅野,失蹤者是張志新(化名)和其女友劉穎终畅,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體竟闪,經(jīng)...
    沈念sama閱讀 44,355評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡离福,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,666評(píng)論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了炼蛤。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片妖爷。...
    茶點(diǎn)故事閱讀 38,809評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖鲸湃,靈堂內(nèi)的尸體忽然破棺而出赠涮,到底是詐尸還是另有隱情子寓,我是刑警寧澤暗挑,帶...
    沈念sama閱讀 34,504評(píng)論 4 334
  • 正文 年R本政府宣布,位于F島的核電站斜友,受9級(jí)特大地震影響炸裆,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜鲜屏,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,150評(píng)論 3 317
  • 文/蒙蒙 一烹看、第九天 我趴在偏房一處隱蔽的房頂上張望国拇。 院中可真熱鬧,春花似錦惯殊、人聲如沸酱吝。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,882評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)务热。三九已至,卻和暖如春己儒,著一層夾襖步出監(jiān)牢的瞬間崎岂,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,121評(píng)論 1 267
  • 我被黑心中介騙來(lái)泰國(guó)打工闪湾, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留冲甘,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,628評(píng)論 2 362
  • 正文 我出身青樓途样,卻偏偏與公主長(zhǎng)得像江醇,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子娘纷,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,724評(píng)論 2 351

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