多线程总结

1 synchronized关键字

package thread;

import java.util.Random;

public class SyncSample {

public static void main(String[] args) {

Couplet c = new Couplet();

for(int i = 0 ; i < 10000 ; i++){

new Thread(){

public void run(){

int r = new Random().nextInt(2);

if(r % 2 == 0){

Couplet.first();

}else{

Couplet.second();

}

}

}.start();

}

}

}

class Couplet{

Object lock = new Object(); //锁对象

public synchronized static void first(){

// synchronized (lock) { //同步代码块,在同一时间只允许有一个线程执行访问这个方法

System.out.printf("琴");

System.out.printf("瑟");

System.out.printf("琵");

System.out.printf("琶");

System.out.println();

// }

}

public static void second(){

synchronized (Couplet.class) { //因为两个同步代码指向了同一把锁lock,所以在同一

个时间内只允许有一个代码块执行,其他等待

System.out.printf("魑");

System.out.printf("魅");

System.out.printf("魍");

System.out.printf("魉");

System.out.println();

}

}

}

package thread;2 死锁

import java.util.Random;

public class SyncSample {

public static void main(String[] args) {

Couplet c = new Couplet();

for(int i = 0 ; i < 10000 ; i++){

new Thread(){

public void run(){

int r = new Random().nextInt(2);

if(r % 2 == 0){

Couplet.first();

}else{

Couplet.second();

}

}

}.start();

}

}

}

class Couplet{

Object lock = new Object(); //锁对象

public synchronized static void first(){

// synchronized (lock) { //同步代码块,在同一时间只允许有一个线程执行访问这个方法

System.out.printf("琴");

System.out.printf("瑟");

System.out.printf("琵");

System.out.printf("琶");

System.out.println();

// }

}

public static void second(){

synchronized (Couplet.class) { //因为两个同步代码指向了同一把锁lock,所以在同一

个时间内只允许有一个代码块执行,其他等待

System.out.printf("魑");

System.out.printf("魅");

System.out.printf("魍");

System.out.printf("魉");

System.out.println();

}

}

}

package thread;

public class DeadLock {

private static String fileA = "A文件";

private static String fileB = "B文件";

public static void main(String[] args) {

new Thread(){ //线程1

public void run(){

while(true) {

synchronized (fileA) {//打开文件A,线程独占3 Thread的方式实现多线程

System.out.println(this.getName() + ":文件A写入");

synchronized (fileB) {

System.out.println(this.getName() + ":文件B写入");

}

System.out.println(this.getName() + ":所有文件保存");

}

}

}

}.start();

new Thread(){ //线程2

public void run(){

while(true) {

synchronized (fileB) {//打开文件A,线程独占

System.out.println(this.getName() + ":文件B写入");

synchronized (fileA) {

System.out.println(this.getName() + ":文件A写入");

}

System.out.println(this.getName() + ":所有文件保存");

}

}

}

}.start();

}

}

package com.itlaoqi.thread;

import java.util.Random;

/**

* 使用集成Thread的方式实现多线程

*/

public class Match1 {

public static void main(String[] args) {

Runner liuxiang = new Runner();//创建一个新的线程

liuxiang.setName("刘翔");//设置线程名称

Runner laoqi = new Runner();

laoqi.setName("老齐");

Runner op = new Runner();

op.setName("路飞");

liuxiang.start();//启动线程

laoqi.start();

op.start();

}

}

class Runner extends Thread{

@Override

public void run() {

Integer speed = new Random().nextInt(100);

for(int i = 1 ; i <= 100 ; i++){

try {4 Runnable方法实现多线程

Thread.sleep(1000); //当前线程休眠1秒

}catch (Exception e){

e.printStackTrace();

}

//this.getName()打印当前线程的名字

System.out.println(this.getName() + "已前进" + (i * speed) + "米(" +

speed + "米/秒)");

}

}

}

package com.itlaoqi.thread;

import java.util.Random;

public class Match2 {

public static void main(String[] args) {

Runner2 liuxiang = new Runner2();

Thread thread1 = new Thread(liuxiang);

thread1.setName("刘翔");

Thread laoqi = new Thread(new Runner2());

laoqi.setName("老齐");

Thread op = new Thread(new Runner2());

op.setName("路飞");

thread1.start();

laoqi.start();

op.start();

}

}

class Runner2 implements Runnable {

@Override

public void run() {

Integer speed = new Random().nextInt(100);

for(int i = 1 ; i <= 100 ; i++){

try {

Thread.sleep(1000); //当前线程休眠1秒

}catch (Exception e){

e.printStackTrace();

}

//Thread.currentThread()用于获取当前执行的线程对象

//在Runnable中是无法使用this获取到当前线程对象的

System.out.println(Thread.currentThread().getName() + "已前进" + (i *

speed) + "米(" + speed + "米/秒)");

}

}

}5 利用线程池实现线程

package thread;

import java.util.Random;

import java.util.concurrent.*;

public class Match3 {

public static void main(String[] args) throws ExecutionException,

InterruptedException {

//创建一个线程池。里面天生有3个“空”线程。Executors是调度器,对线程池进行管理

ExecutorService executorService = Executors.newFixedThreadPool(3);

Runner3 liuxiang = new Runner3();//实例化Callable对象

liuxiang.setName("刘翔");

Runner3 laoqi = new Runner3();

laoqi.setName("老齐");

Runner3 op = new Runner3();

op.setName("路飞");

//将这个对象扔到线程池中,线程池自动分配一个线程来运行liuxiang这个对象的call方法

//Future用于接受线程内部call方法的返回值

Future<Integer> result1 = executorService.submit(liuxiang);

Future<Integer> result2 = executorService.submit(laoqi);

Future<Integer> result3 = executorService.submit(op);

try {

Thread.sleep(5000);

} catch (InterruptedException e) {

e.printStackTrace();

}

executorService.shutdown();//关闭线程池释放所有资源

System.out.println("刘翔累计跑了" + result1.get() + "米" );

System.out.println("老齐累计跑了" + result2.get() + "米" );

System.out.println("路飞累计跑了" + result3.get() + "米" );

}

}

class Runner3 implements Callable<Integer>{

private String name ;

public void setName(String name){

this.name = name;

}

//实现Callable接口可以允许我们的线程返回值或抛出异常

@Override

public Integer call() throws Exception {

Integer speed = new Random().nextInt(100);

Integer distince = 0; //总共奔跑的距离

for(int i = 1 ; i <= 100 ; i++){

Thread.sleep(10);

distince = i * speed;

System.out.println(this.name + "已前进" + distince + "米(" + speed +

"米/秒)");

}

return distince;

}6 可缓存线程池

7 定长线程池

}

package com.itlaoqi.juc;

import java.util.concurrent.ExecutorService;

import java.util.concurrent.Executors;

public class ThreadPoolSample1 {

public static void main(String[] args) {

//调度器对象

//ExecutorService用于管理线程池

ExecutorService threadPool = Executors.newCachedThreadPool();//创建一个可

缓存线程池

//可缓存线程池的特点是,无限大,如果线程池中没有可用的线程则创建,有空闲线程则利用起来

for(int i = 1 ; i <= 1000 ; i++) {

final int index = i;

threadPool.execute(new Runnable() {

@Override

public void run() {

System.out.println(Thread.currentThread().getName() + ":" +

index);

}

});

}

try {

Thread.sleep(1000); //跟线程足够的运行时间

} catch (InterruptedException e) {

e.printStackTrace();

}

//shutdown() 代表关闭线程池(等待所有线程完成)

//shutdownNow() 代表立即终止线程池的运行,不等待线程,不推荐使用

threadPool.shutdown();

}

}

package com.itlaoqi.juc;

import java.util.concurrent.ExecutorService;

import java.util.concurrent.Executors;

public class ThreadPoolSample2 {

public static void main(String[] args) {

//调度器对象

//ExecutorService用于管理线程池

ExecutorService threadPool = Executors.newFixedThreadPool(10);//创建一个可

创建一个定长线程池

//定长线程池的特点是固定线程总数,空间线程用于执行任务,如果线程都在使用后续任务则处于

等待状态,在线程池中的线程8 单线程池

//如果任务处于等待的状态,备选的等待算法默认为FIFO(先进先出) LIFO(后进先出)

//执行任务后再执行后续的任务。

for(int i = 1 ; i <= 1000 ; i++) {

final int index = i;

threadPool.execute(new Runnable() {

@Override

public void run() {

System.out.println(Thread.currentThread().getName() + ":" +

index);

}

});

}

try {

Thread.sleep(1000); //跟线程足够的运行时间

} catch (InterruptedException e) {

e.printStackTrace();

}

//shutdown() 代表关闭线程池(等待所有线程完成)

//shutdownNow() 代表立即终止线程池的运行,不等待线程,不推荐使用

threadPool.shutdown();

}

}

package com.itlaoqi.juc;

import java.util.concurrent.ExecutorService;

import java.util.concurrent.Executors;

public class ThreadPoolSample3 {

public static void main(String[] args) {

//调度器对象

//ExecutorService用于管理线程池

ExecutorService threadPool = Executors.newSingleThreadExecutor();//单线程

线程池

for(int i = 1 ; i <= 1000 ; i++) {

final int index = i;

threadPool.execute(new Runnable() {

@Override

public void run() {

System.out.println(Thread.currentThread().getName() + ":" +

index);

}

});

}

try {

Thread.sleep(1000); //跟线程足够的运行时间

} catch (InterruptedException e) {

e.printStackTrace();

}

//shutdown() 代表关闭线程池(等待所有线程完成)

//shutdownNow() 代表立即终止线程池的运行,不等待线程,不推荐使用

threadPool.shutdown();

}

}9 可以调度的线程池

10 condition用于线程排序

我们在并行程序中,避免不了某些线程要预先规定好的顺序执行,

例如:先新增再修改,先买后卖,先进后出......,对于这类场景,使

用JUC的Condition对象再合适不过了。

u JUC中提供了Condition对象,用于让指定线程等待与唤醒,按预期

顺序执行。它必须和ReentrantLock重入锁配合使用。

u Condition用于替代wait()/notify()方法

– notify只能随机唤醒等待的线程,而Condition可以唤醒指定的线程,这有利于更好

的控制并发程序。

package com.itlaoqi.juc;

import java.util.Date;

import java.util.concurrent.Executors;

import java.util.concurrent.ScheduledExecutorService;

import java.util.concurrent.TimeUnit;

public class

ThreadPoolSample4 {

public static void main(String[] args) {

ScheduledExecutorService scheduledThreadPool =

Executors.newScheduledThreadPool(5);//可调度线程池

/*//延迟三秒执行一次Run方法

scheduledThreadPool.schedule(new Runnable() {

@Override

public void run() {

System.out.println("延迟3秒执行");

}

} , 3 , TimeUnit.SECONDS);*/

//Timer , 项目实际开发中scheduledThreadPool与Timer都不会用到,应为有成熟的调度框

架Quartz,或者Spring自带调度,

//程序的调度框架支持一种表达式叫做Cron表达式,有兴趣的童鞋可以了解一下。

scheduledThreadPool.scheduleAtFixedRate(new Runnable() {

@Override

public void run() {

System.out.println(new Date() + "延迟1秒执行,每三秒执行一次");

}

}, 1, 3, TimeUnit.SECONDS);

}

}

package juc;//测试唤醒操作

import java.util.concurrent.locks.Condition;

import java.util.concurrent.locks.ReentrantLock;

public class CoditionSample {

public static void main(String[] args) {

ReentrantLock lock=new ReentrantLock();//condition需要配合lock一起使用

Condition c2=lock.newCondition();

Condition c3=lock.newCondition();

Condition c1=lock.newCondition();

new Thread(new Runnable() {

@Override

public void run() {

try {

lock.lock();

Thread.sleep(1000);

c1.await(); //阻塞改线程 c1.singal的时候会被调用

System.out.println("粒粒也辛苦");

} catch (InterruptedException e) {

e.printStackTrace();

}finally {

lock.unlock();

}

}

;

}).start();

new Thread(new Runnable() {

@Override

public void run() {

try {

lock.lock();

Thread.sleep(1000);

c3.await(); //阻塞改线程 c1.singal的时候会被调用

System.out.println("谁知盘中餐");

c1.signal();

} catch (InterruptedException e) {

e.printStackTrace();

}finally {

lock.unlock();

}

}

}).start();

new Thread(new Runnable() {

@Override

public void run() {

try {

lock.lock();

c2.await(); //阻塞改线程 c1.singal的时候会被调用

Thread.sleep(1000);1 1 cyclicBarrier循环屏障

CyclicBarrier是一个同步工具类,它允许一组线程互相等

待,直到到达某个公共屏障点。与CountDownLatch不同

的是该barrier在释放等待线程后可以重用,所以称它为循

环(Cyclic)的屏障(Barrier)

System.out.println("汗滴和下土");

c3.signal();

} catch (InterruptedException e) {

e.printStackTrace();

}finally {

lock.unlock();

}

}

}).start();

new Thread(new Runnable() {

@Override

public void run() {

lock.lock();

try {

Thread.sleep(1000);

System.out.println("锄禾日当午");

c2.signal();

}catch (Exception e){

e.printStackTrace();

}finally {

lock.unlock();

}

}

}).start();

}

}

package juc;

import java.util.concurrent.BrokenBarrierException;

import java.util.concurrent.CyclicBarrier;

import java.util.concurrent.ExecutorService;

import java.util.concurrent.Executors;

public class CyclicBarrierSample {

private static CyclicBarrier cyclicBarrier = new CyclicBarrier(5);12 CountDownLatch - 倒计时锁

CountDownLatch倒计时锁特别适合”总-分任务”,

例如多线程计算后的数据汇总

u CountDownLatch类位于java.util.concurrent

(J.U.C)**包下,利用它可以实现类似计数器的功能。**

比如有一个任务A,它要等待其他3个任务执行完毕之

后才能执行,此时就可以利用CountDownLatch来实

现这种功能了

public static void main(String[] args) {

ExecutorService executorService = Executors.newCachedThreadPool();

for(int i = 1 ; i<=20 ; i++) {

final int index = i;

try {

Thread.sleep(1000);

} catch (InterruptedException e) {

e.printStackTrace();

}

executorService.execute(new Runnable() {

@Override

public void run() {

go();

}

});

}

executorService.shutdown();

}

private static void go(){

System.out.println(Thread.currentThread().getName() + ":准备就绪" );

try {

cyclicBarrier.await();//设置屏障点,当累计5个线程都准备好后,才运行后面的代码

System.out.println(Thread.currentThread().getName() + ":开始运行");

} catch (InterruptedException e) {

e.printStackTrace();

} catch (BrokenBarrierException e) {

e.printStackTrace();

}

}

}

package juc;

import java.util.concurrent.CountDownLatch;

import java.util.concurrent.ExecutorService;

import java.util.concurrent.Executors;

public class CountDownSample {13 信号量

Semaphore信号量经常用于限制获取某种资源的线程数量。下面举个例子,

比如说操场上有5个跑道,一个跑道一次只能有一个学生在上面跑步,一旦

所有跑道在使用,那么后面的学生就需要等待,直到有一个学生不跑了

private static int count = 0;

public static void main(String[] args) {

ExecutorService threadPool = Executors.newFixedThreadPool(100);

CountDownLatch cdl = new CountDownLatch(10000); //CDL总数和操作数保持一致

for(int i = 1 ; i <= 10000 ; i++) {

final int index = i;

threadPool.execute(new Runnable() {

@Override

public void run() {

synchronized (CountDownSample.class) {

try {

count = count + index;

//计数器减一

}catch(Exception e){

e.printStackTrace();

}finally {

cdl.countDown();

}

}

}

});

}

/* try {

Thread.sleep(1000);

} catch (InterruptedException e) {

e.printStackTrace();

}*/

try {

cdl.await(); //堵塞当前线程,知道cdl=0的时候再继续往下走

//为了避免程序一致挂起,我们可以设置一个timeout时间

} catch (InterruptedException e) {

e.printStackTrace();

}

System.out.println(count);

threadPool.shutdown();

}

}

package juc;

import java.util.Date;

import java.util.concurrent.ExecutorService;

import java.util.concurrent.Executors;

import java.util.concurrent.Semaphore;

public class SemaphoreSample1 {

public static void main(String[] args) {

ExecutorService threadPool = Executors.newCachedThreadPool();14 Callable&Future

Callable和Runnable一样代表着任务,区别在于**

Callable有返回值并且可以抛出异常。

Future 是一个接口。它用于表示异步计算的结果。提

供了检查计算是否完成的方法,以等待计算的完成,

并获取计算的结果

Semaphore semaphore = new Semaphore(5);//定义5个信号量,也就是说服务器只允许5

个人在里面玩

for(int i = 1 ; i <= 20 ; i++) {

final int index = i;

threadPool.execute(new Runnable() {

@Override

public void run() {

try {

semaphore.acquire();//获取一个信号量,“占用一个跑到”

play();

semaphore.release();//执行完成后释放这个信号量,“从跑道出去”

} catch (InterruptedException e) {

e.printStackTrace();

}

}

});

}

threadPool.shutdown();

}

public static void play(){

try {

System.out.println(new Date() + " " +

Thread.currentThread().getName() + ":获得紫禁之巅服务器进入资格");

Thread.sleep(2000);

System.out.println(new Date() + " " +

Thread.currentThread().getName() + ":退出服务器");

Thread.sleep(500);

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}

package juc;

import com.sun.org.apache.xpath.internal.operations.Bool;

import java.util.concurrent.*;

public class FutureSample {

public static void main(String[] args) {

ExecutorService executorService = Executors.newFixedThreadPool(10);15 重入锁

重入锁是指任意线程在获取到锁之后,再次获取该锁而不会被该锁

所阻塞

ReentrantLock设计的目标是用来替代synchronized关键字

for(int i = 2 ; i <= 10000 ; i++){

Computor c = new Computor();

c.setNum(i);

//Future是对用于计算的线程进行监听,因为计算是在其他线程中执行的,所以这个返回结

果的过程是异步的

Future<Boolean> result = executorService.submit(c);//将c对象提交给线程

池,如有空闲线程立即执行里面的call方法

try {

Boolean r = result.get(); //用于获取返回值,如果线程内部的call没有执行

完成,则进入等待状态,直到计算完成

if(r == true){

System.out.println(c.getNum());

}

} catch (InterruptedException e) {

e.printStackTrace();

} catch (ExecutionException e) {

e.printStackTrace();

}

}

executorService.shutdown();

}

}

class Computor implements Callable<Boolean>{

private Integer num;

public Integer getNum() {

return num;

}

public void setNum(Integer num) {

this.num = num;

}

@Override

public Boolean call() throws Exception {

boolean isprime = true;

for(int i = 2 ; i < num ; i++) {

if (num % i == 0) {

isprime = false;

break;

}

}

return isprime;

}

}16 juc之并发容器

ArrayList -> CopyOnWriteArrayList - 写复制列表

package com.itlaoqi.juc;

import java.util.concurrent.ExecutorService;

import java.util.concurrent.Executors;

import java.util.concurrent.Semaphore;

import java.util.concurrent.locks.ReentrantLock;

public class ReentrantLockSample {

public static int users = 100;//同时模拟的并发访问用户数量

public static int downTotal = 50000; //用户下载的真实总数

public static int count = 0 ;//计数器

private static ReentrantLock lock = new ReentrantLock();

public static void main(String[] args) {

//调度器,JDK1.5后提供的concurrent包对于并发的支持

ExecutorService executorService = Executors.newCachedThreadPool();

//信号量,用于模拟并发的人数

final Semaphore semaphore = new Semaphore(users);

for(int i = 0 ; i < downTotal ; i++){

executorService.execute(()->{

//通过多线程模拟N个用户并发访问并下载

try {

semaphore.acquire();

add();

semaphore.release();

} catch (Exception e) {

e.printStackTrace();

}

});

}

try {

Thread.sleep(3000);

} catch (InterruptedException e) {

e.printStackTrace();

}

executorService.shutdown();//关闭调度服务

System.out.println("下载总数:" + count);

}

//线程不安全

public static void add(){

lock.lock();//上锁

try {

count++;

}finally {

lock.unlock(); //解锁,一定要放在finally里面否则会出现死锁

}

}

}u HashSet -> CopyOnWriteArraySet - 写复制集合

u HashMap -> ConcurrentHashMap - 分段锁映射

package juc;

import java.util.HashMap;

import java.util.Hashtable;

import java.util.concurrent.ConcurrentHashMap;

import java.util.concurrent.ExecutorService;

import java.util.concurrent.Executors;

import java.util.concurrent.Semaphore;

public class ConcurrentHashMapSample {

public static int users = 100;//同时模拟的并发访问用户数量

public static int downTotal = 50000; //用户下载的真实总数

public static ConcurrentHashMap count = new ConcurrentHashMap() ;//计数器

public static void main(String[] args) {

ExecutorService executorService = Executors.newCachedThreadPool();

final Semaphore semaphore = new Semaphore(users);

for(int i = 0 ; i < downTotal ; i++){

final Integer index = i;

executorService.execute(()->{

//通过多线程模拟N个用户并发访问并下载

try {

semaphore.acquire();

count.put(index, index);

semaphore.release();

} catch (Exception e) {

e.printStackTrace();

}

});

}

try {

Thread.sleep(3000);

} catch (InterruptedException e) {

e.printStackTrace();

}

executorService.shutdown();//关闭调度服务

System.out.println("下载总数:" + count.size());

}

}

写复制列表

package juc;

import java.util.ArrayList;

import java.util.Iterator;

import java.util.List;

import java.util.concurrent.CopyOnWriteArrayList;

public class CopyOnWriteArrayListSample {17 cas算法和乐观锁

原子性:是指一个操作或多个操作要么全部执行,且

执行的过程不会被任何因素打断,要么就都不执行

Atomic常用类

– AtomicInteger

– AtomicIntegerArray

– AtomicBoolean

– AtomicLong

– AtomicLongArray

public static void main(String[] args) {

//写复制列表

List<Integer> list = new CopyOnWriteArrayList<>();

for(int i = 0 ; i < 1000 ; i++){

list.add(i);

}

Iterator<Integer> itr = list.iterator();

while (itr.hasNext()) {

Integer i = itr.next();

list.remove(i);

}

System.out.println(list);

}

}

package juc;

import java.util.concurrent.ExecutorService;

import java.util.concurrent.Executors;

import java.util.concurrent.Semaphore;

import java.util.concurrent.atomic.AtomicInteger;

public class AtomicIntegerSample {

public static int users = 100;//同时模拟的并发访问用户数量

public static int downTotal = 50000; //用户下载的真实总数

public static AtomicInteger count = new AtomicInteger() ;//计数器

public static void main(String[] args) {

//调度器,JDK1.5后提供的concurrent包对于并发的支持

ExecutorService executorService = Executors.newCachedThreadPool();

//信号量,用于模拟并发的人数

final Semaphore semaphore = new Semaphore(users);

for(int i = 0 ; i < downTotal ; i++){

executorService.execute(()->{

//通过多线程模拟N个用户并发访问并下载

try {

semaphore.acquire();add();

semaphore.release();

} catch (Exception e) {

e.printStackTrace();

}

});

}

try {

Thread.sleep(3000);

} catch (InterruptedException e) {

e.printStackTrace();

}

executorService.shutdown();//关闭调度服务

System.out.println("下载总数:" + count);

}

//线程不安全

public static void add(){

count.getAndIncrement(); //count++

}

/*线程安全

public synchronized static void add(){

count++;

}*/

}

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,634评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,951评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,427评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,770评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,835评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,799评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,768评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,544评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,979评论 1 308
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,271评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,427评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,121评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,756评论 3 324
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,375评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,579评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,410评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,315评论 2 352