iOS多线程之NSThread,GCD,NSOperation

timg.jpeg

基本概念

进程: 一个具有一定独立功能的程序关于某个数据集合的一次运行活动。可以理解成一个运行中的应用程序。
线程: 程序执行流的最小单元,线程是进程中的一个实体。
同步: 只能在当前线程按先后顺序依次执行,不开启新线程。
异步: 可以在当前线程开启多个新线程执行,可不按顺序执行。
队列: 装载线程任务的队形结构。
并发: 线程执行可以同时一起进行执行。
串行: 线程执行只能依次逐一先后有序的执行。一个进程可以有多个线程,也可以有多个队列。

iOS多线程对比

  1. NSThread
    每个NSThread对象对应一个线程,真正最原始的线程。
    1)优点:NSThread 轻量级最低,相对简单。
    2)缺点:手动管理所有的线程活动,如生命周期、线程同步、睡眠等。

  2. NSOperation
    自带线程管理的抽象类。
    1)优点:自带线程周期管理,操作上可更注重自己逻辑。
    2)缺点:面向对象的抽象类,只能实现它或者使用它定义好的两个子类:NSInvocationOperation 和 NSBlockOperation。

  3. GCD
    Grand Central Dispatch (GCD)是Apple开发的一个多核编程的解决方法。
    1)优点:最高效,避开并发陷阱。
    2)缺点:基于C实现。

  4. 选择小结
    1)简单而安全的选择NSOperation实现多线程即可。
    2)处理大量并发数据,又追求性能效率的选择GCD。
    3)NSThread用的少。

1. NSThread 创建方法一

- (void)viewDidLoad {
    [super viewDidLoad];
    
    // 创建线程
    NSThread *thread = [[NSThread alloc]initWithTarget:self selector: @selector(run:) object:@"hehe"];
    //线程名字
    thread.name = @"wang";
    //开启线程
    [thread start];
    
}
- (void)run:(NSString*)str
{
    //d[2177:95263] -----run-----hehe--<NSThread: 0x60000026e440>{number = 3, name = wang}
     NSLog(@"-----run-----%@--%@", str, [NSThread currentThread]);
}

2. NSThread 其他创建方法

//方法二
[self performSelectorInBackground:@selector(run:) withObject:@"wang"];
//方法三

 [NSThread detachNewThreadSelector:@selector(run:) toTarget:self withObject:@"wang"];

3. 线程的状态

9F77DB76-6699-4DFE-BAFC-C9E6A8F5B534.png

4. 线程安全

//self 是锁对象
@synchronized(self) {
            //执行多线程操作
}

5. NSThread的其他api

// 获得主线程
+ (NSThread *)mainThread; 

// 是否为主线程
- (BOOL)isMainThread; 

// 是否为主线程
+ (BOOL)isMainThread; 

//获得当前线程
NSThread *current = [NSThread currentThread];

//线程的名字
- (void)setName:(NSString *)n;
- (NSString *)name;

//启动线程,进入就绪状态 -> 运行状态。当线程任务执行完毕,自动进入死亡状态
- (void)start; 

//阻塞(暂停)线程
+ (void)sleepUntilDate:(NSDate *)date;
+ (void)sleepForTimeInterval:(NSTimeInterval)ti;

//强制停止线程进入死亡状态一旦线程停止(死亡)了,就不能再次开启任务
+ (void)exit;

//线程间通信常用方法
- (void)performSelectorOnMainThread:(SEL)aSelector withObject:(id)arg waitUntilDone:(BOOL)wait;
- (void)performSelector:(SEL)aSelector onThread:(NSThread *)thr withObject:(id)arg waitUntilDone:(BOOL)wait;

6. GCD的任务和队列

  • 异步函数 + 并发队列:可以同时开启多条线程
/**
 * 异步函数 + 并发队列:可以同时开启多条线程
 */
- (void)asyncConcurrent
{
    // 1.创建一个并发队列
    // label : 相当于队列的名字
    // attr  : 并行 DISPATCH_QUEUE_CONCURRENT 串行 DISPATCH_QUEUE_SERIAL == NULL
//    dispatch_queue_t queue = dispatch_queue_create("wang", DISPATCH_QUEUE_CONCURRENT);
    
    // 1.获得全局的并发队列
    //#define DISPATCH_QUEUE_PRIORITY_HIGH 2
    //#define DISPATCH_QUEUE_PRIORITY_DEFAULT 0
    //#define DISPATCH_QUEUE_PRIORITY_LOW (-2)
    //#define DISPATCH_QUEUE_PRIORITY_BACKGROUND INT16_MIN
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    
    // 2.将任务加入队列
    dispatch_async(queue, ^{
        for (NSInteger i = 0; i<2; i++) {
            NSLog(@"1-----%@", [NSThread currentThread]);
        }
    });
    dispatch_async(queue, ^{
        for (NSInteger i = 0; i<2; i++) {
            NSLog(@"2-----%@", [NSThread currentThread]);
        }
    });
    dispatch_async(queue, ^{
        for (NSInteger i = 0; i<2; i++) {
            NSLog(@"3-----%@", [NSThread currentThread]);
        }
    });
    
//    2017-03-28 17:10:40.609 07-GCD的基本使用[5361:272988] 3-----<NSThread: 0x60800026b9c0>{number = 5, name = (null)}
//    2017-03-28 17:10:40.609 07-GCD的基本使用[5361:272971] 1-----<NSThread: 0x60800026ba80>{number = 3, name = (null)}
//    2017-03-28 17:10:40.609 07-GCD的基本使用[5361:272973] 2-----<NSThread: 0x60800026be40>{number = 4, name = (null)}
//    2017-03-28 17:10:40.614 07-GCD的基本使用[5361:272988] 3-----<NSThread: 0x60800026b9c0>{number = 5, name = (null)}
//    2017-03-28 17:10:40.615 07-GCD的基本使用[5361:272971] 1-----<NSThread: 0x60800026ba80>{number = 3, name = (null)}
//    2017-03-28 17:10:40.615 07-GCD的基本使用[5361:272973] 2-----<NSThread: 0x60800026be40>{number = 4, name = (null)}
    
    
}

  • 同步函数 + 并发队列:不会开启新的线程
/**
 * 同步函数 + 并发队列:不会开启新的线程
 */
- (void)syncConcurrent
{
    // 1.获得全局的并发队列
    //#define DISPATCH_QUEUE_PRIORITY_HIGH 2
    //#define DISPATCH_QUEUE_PRIORITY_DEFAULT 0
    //#define DISPATCH_QUEUE_PRIORITY_LOW (-2)
    //#define DISPATCH_QUEUE_PRIORITY_BACKGROUND INT16_MIN
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    
    // 2.将任务加入队列
    dispatch_sync(queue, ^{
        NSLog(@"1-----%@", [NSThread currentThread]);
    });
    dispatch_sync(queue, ^{
        NSLog(@"2-----%@", [NSThread currentThread]);
    });
    dispatch_sync(queue, ^{
        NSLog(@"3-----%@", [NSThread currentThread]);
    });
    
//    2017-03-28 17:13:31.051 07-GCD的基本使用[5403:275128] 1-----<NSThread: 0x608000263940>{number = 1, name = main}
//    2017-03-28 17:13:31.053 07-GCD的基本使用[5403:275128] 2-----<NSThread: 0x608000263940>{number = 1, name = main}
//    2017-03-28 17:13:31.054 07-GCD的基本使用[5403:275128] 3-----<NSThread: 0x608000263940>{number = 1, name = main}
    
    
}


  • 异步函数 + 串行队列:会开启新的线程,但是任务是串行的,执行完一个任务,再执行下一个任务
/**
 * 异步函数 + 串行队列:会开启新的线程,但是任务是串行的,执行完一个任务,再执行下一个任务
 */
- (void)asyncSerial
{
    // 1.创建串行队列
    //#define DISPATCH_QUEUE_SERIAL NULL
    dispatch_queue_t queue = dispatch_queue_create("wang", NULL);

    
    // 2.将任务加入队列
    dispatch_async(queue, ^{
        NSLog(@"1-----%@", [NSThread currentThread]);
    });
    dispatch_async(queue, ^{
        NSLog(@"2-----%@", [NSThread currentThread]);
    });
    dispatch_async(queue, ^{
        NSLog(@"3-----%@", [NSThread currentThread]);
    });
    
//    2017-03-28 17:16:02.187 07-GCD的基本使用[5495:278209] 1-----<NSThread: 0x608000262440>{number = 3, name = (null)}
//    2017-03-28 17:16:02.187 07-GCD的基本使用[5495:278209] 2-----<NSThread: 0x608000262440>{number = 3, name = (null)}
//    2017-03-28 17:16:02.188 07-GCD的基本使用[5495:278209] 3-----<NSThread: 0x608000262440>{number = 3, name = (null)}
}

  • 同步函数 + 串行队列:不会开启新的线程,在当前线程执行任务。任务是串行的,执行完一个任务,再执行下一个任务
/**
 * 同步函数 + 串行队列:不会开启新的线程,在当前线程执行任务。任务是串行的,执行完一个任务,再执行下一个任务
 */
- (void)syncSerial
{
    // 1.创建串行队列
    dispatch_queue_t queue = dispatch_queue_create("wang", DISPATCH_QUEUE_SERIAL);
    
    // 2.将任务加入队列
    dispatch_sync(queue, ^{
        NSLog(@"1-----%@", [NSThread currentThread]);
    });
    dispatch_sync(queue, ^{
        NSLog(@"2-----%@", [NSThread currentThread]);
    });
    dispatch_sync(queue, ^{
        NSLog(@"3-----%@", [NSThread currentThread]);
    });
    
//    2017-03-28 17:17:25.275 07-GCD的基本使用[5527:279554] 1-----<NSThread: 0x6000000757c0>{number = 1, name = main}
//    2017-03-28 17:17:25.275 07-GCD的基本使用[5527:279554] 2-----<NSThread: 0x6000000757c0>{number = 1, name = main}
//    2017-03-28 17:17:25.275 07-GCD的基本使用[5527:279554] 3-----<NSThread: 0x6000000757c0>{number = 1, name = main}
    
}

  • 异步函数 + 主队列:只在主线程中执行任务
/**
 * 异步函数 + 主队列:只在主线程中执行任务
 */
- (void)asyncMain
{
    // 1.获得主队列
    dispatch_queue_t queue = dispatch_get_main_queue();
    
    // 2.将任务加入队列
    dispatch_async(queue, ^{
        NSLog(@"1-----%@", [NSThread currentThread]);
    });
    dispatch_async(queue, ^{
        NSLog(@"2-----%@", [NSThread currentThread]);
    });
    dispatch_async(queue, ^{
        NSLog(@"3-----%@", [NSThread currentThread]);
    });
    
//    2017-03-28 17:20:38.682 07-GCD的基本使用[5591:282861] 1-----<NSThread: 0x600000065a40>{number = 1, name = main}
//    2017-03-28 17:20:38.683 07-GCD的基本使用[5591:282861] 2-----<NSThread: 0x600000065a40>{number = 1, name = main}
//    2017-03-28 17:20:38.683 07-GCD的基本使用[5591:282861] 3-----<NSThread: 0x600000065a40>{number = 1, name = main}
}
  • 同步函数 + 主队列:堵塞主线程,禁用
/**
 * 同步函数 + 主队列:
 */
- (void)syncMain
{
    NSLog(@"syncMain ----- begin");
    
    // 1.获得主队列
    dispatch_queue_t queue = dispatch_get_main_queue();
    
    // 2.将任务加入队列
    dispatch_sync(queue, ^{
        NSLog(@"1-----%@", [NSThread currentThread]);
    });
    dispatch_sync(queue, ^{
        NSLog(@"2-----%@", [NSThread currentThread]);
    });
    dispatch_sync(queue, ^{
        NSLog(@"3-----%@", [NSThread currentThread]);
    });
    
    NSLog(@"syncMain ----- end");
}

7. GCD线程间的通信

 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
          //执行异步操作
        
        // 回到主线程
        dispatch_async(dispatch_get_main_queue(), ^{
            //刷新UI
        });
    });

8. GCD延时执行

/**
 * 延迟执行
 */
- (void)delay
{
    
    //方法1
    [self performSelector:@selector(run) withObject:nil afterDelay:2.0];
    
    //方法2
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        
        NSLog(@"延迟执行");
    });
    
    //方法3
    [NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:@selector(run) userInfo:nil repeats:NO];
    
}

8. GCD只执行1次的代码dispatch_once

- (void)once
{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        NSLog(@"只执行1次的代码dispatch_once");
    });
    
}

9. GCD的dispatch_barrier栅栏

- (void)barrier
{
    dispatch_queue_t queue = dispatch_queue_create("12312312", DISPATCH_QUEUE_CONCURRENT);
    
    dispatch_async(queue, ^{
        NSLog(@"----1-----%@", [NSThread currentThread]);
    });
    dispatch_async(queue, ^{
        NSLog(@"----2-----%@", [NSThread currentThread]);
    });

    
    dispatch_barrier_async(queue, ^{
        NSLog(@"----barrier-----%@", [NSThread currentThread]);
    });
    
    dispatch_async(queue, ^{
        NSLog(@"----3-----%@", [NSThread currentThread]);
    });
    dispatch_async(queue, ^{
        NSLog(@"----4-----%@", [NSThread currentThread]);
    });
 
//    2017-03-29 10:20:17.716 [1321:43448] ----1-----<NSThread: 0x608000264740>{number = 3, name = (null)}
//    2017-03-29 10:20:17.716 [1321:43722] ----2-----<NSThread: 0x60800007f7c0>{number = 4, name = (null)}
//    2017-03-29 10:20:17.716 [1321:43722] ----barrier-----<NSThread: 0x60800007f7c0>{number = 4, name = (null)}
//    2017-03-29 10:20:17.717 [1321:43722] ----3-----<NSThread: 0x60800007f7c0>{number = 4, name = (null)}
//    2017-03-29 10:20:17.717 [1321:43448] ----4-----<NSThread: 0x608000264740>{number = 3, name = (null)}

}

10. GCD的dispatch_apply

- (void)apply
{
  
    
    NSMutableArray *arr = [NSMutableArray array];
    
    for (int i=0; i<10; i++) {
        
        [arr addObject:@(i)];
    }
    
     dispatch_queue_t queue1 = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_apply(arr.count, queue1, ^(size_t index) {
        
        NSLog(@"%ld",index);
        
    });
    
//    2017-03-29 10:44:58.489 [1877:73243] 2
//    2017-03-29 10:44:58.489 [1877:73244] 1
//    2017-03-29 10:44:58.489 [1877:73213] 0
//    2017-03-29 10:44:58.489 [1877:73246] 3
//    2017-03-29 10:44:58.489 [1877:73243] 4
//    2017-03-29 10:44:58.489 [1877:73244] 5
//    2017-03-29 10:44:58.489 [1877:73213] 6
//    2017-03-29 10:44:58.489 [1877:73246] 7
//    2017-03-29 10:44:58.489 [1877:73243] 8
//    2017-03-29 10:44:58.490 [1877:73244] 9
    
}

11. GCD的dispatch_group

- (void)group
{
    
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    // 创建一个队列组
    dispatch_group_t group = dispatch_group_create();
    
    
    dispatch_group_async(group, queue, ^{
      
        NSLog(@"1");
        
    });
    
    dispatch_group_async(group, queue, ^{
        NSLog(@"2");
    });
    
    dispatch_group_notify(group, queue, ^{
        NSLog(@"完成了");
    });
    
//    2017-03-29 10:48:53.947 [1939:76156] 2
//    2017-03-29 10:48:53.947 [1939:76157] 1
//    2017-03-29 10:48:53.947 [1939:76157] 完成了
}

11. NSOperation的使用

- (void)blockOperation
{
    NSBlockOperation *op = [NSBlockOperation blockOperationWithBlock:^{
        // 在主线程
        NSLog(@"下载1------%@", [NSThread currentThread]);
    }];
    
    // 添加额外的任务(在子线程执行)
    [op addExecutionBlock:^{
        NSLog(@"下载2------%@", [NSThread currentThread]);
    }];

    [op addExecutionBlock:^{
        NSLog(@"下载3------%@", [NSThread currentThread]);
    }];
    [op addExecutionBlock:^{
        NSLog(@"下载4------%@", [NSThread currentThread]);
    }];
    
    [op start];
}

- (void)invocationOperation
{
    NSInvocationOperation *op = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(run) object:nil];

    [op start];
}

- (void)run
{
    NSLog(@"------%@", [NSThread currentThread]);
}

12. NSOperationQueue的使用

NSOperationQueue *queue = [[NSOperationQueue alloc] init];是可以开启线程的,串行和并行通过maxConcurrentOperationCount设置,为1的时候就是串行。[NSOperationQueue mainQueue]是在主线程执行任务。串行的

- (void)operationQueue1
{
    // 创建队列
    NSOperationQueue *queue = [[NSOperationQueue alloc] init];
    
    // 创建操作(任务)
    // 创建NSInvocationOperation
    NSInvocationOperation *op1 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(download1) object:nil];
    
    // 创建NSBlockOperation
    NSBlockOperation *op3 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"download3 --- %@", [NSThread currentThread]);
    }];
    
    [op3 addExecutionBlock:^{
        NSLog(@"download4 --- %@", [NSThread currentThread]);
    }];
    
    // 添加任务到队列中
    [queue addOperation:op1]; // [op1 start]
    [queue addOperation:op3]; // [op3 start]

}

- (void)operationQueue2
{
    // 创建队列
    NSOperationQueue *queue = [[NSOperationQueue alloc] init];
  
    [queue addOperationWithBlock:^{
        NSLog(@"download1 --- %@", [NSThread currentThread]);
    }];
    [queue addOperationWithBlock:^{
        NSLog(@"download2 --- %@", [NSThread currentThread]);
    }];
}

- (void)opetationQueue3
{
    // 创建队列
    NSOperationQueue *queue = [[NSOperationQueue alloc] init];
    
    // 设置最大并发操作数
    //    queue.maxConcurrentOperationCount = 2;
    queue.maxConcurrentOperationCount = 1; // 就变成了串行队列
    
    // 添加操作
    [queue addOperationWithBlock:^{
        NSLog(@"download1 --- %@", [NSThread currentThread]);
        
    }];
    [queue addOperationWithBlock:^{
        NSLog(@"download2 --- %@", [NSThread currentThread]);
        
    }];
   
}

- (void)suspend
{
    if (self.queue.isSuspended) {
        // 恢复队列,继续执行
        self.queue.suspended = NO;
    } else {
        // 暂停(挂起)队列,暂停执行
        self.queue.suspended = YES;
    }
    
    
    //取消任务
    [self.queue cancelAllOperations];
}

12. 自定义NSOperation的使用

@interface MyOperation : NSOperation

@end

@implementation MyOperation

/**
 * 需要执行的任务
 */
- (void)main
{
    NSLog(@"需要执行的任务");
}

@end

13. 任务之间添加依赖addDependency

- (void) addDependency{
    NSOperationQueue *queue = [[NSOperationQueue alloc] init];
    
    NSBlockOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"download1----%@", [NSThread  currentThread]);
    }];
    NSBlockOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"download2----%@", [NSThread  currentThread]);
    }];
    NSBlockOperation *op3 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"download3----%@", [NSThread  currentThread]);
    }];
    NSBlockOperation *op4 = [NSBlockOperation blockOperationWithBlock:^{
        for (NSInteger i = 0; i<10; i++) {
            NSLog(@"download4----%@", [NSThread  currentThread]);
        }
    }];
    NSBlockOperation *op5 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"download5----%@", [NSThread  currentThread]);
    }];
    op5.completionBlock = ^{
        NSLog(@"op5执行完毕---%@", [NSThread currentThread]);
    };
    
    // 设置依赖
    [op3 addDependency:op1];
    [op3 addDependency:op2];
    [op3 addDependency:op4];
    
    [queue addOperation:op1];
    [queue addOperation:op2];
    [queue addOperation:op3];
    [queue addOperation:op4];
    [queue addOperation:op5];
}

13. 线程之间的通信

/**
 * 线程之间的通信
 */
- (void)test
{
    [[[NSOperationQueue alloc] init] addOperationWithBlock:^{
        // 图片的网络路径
       NSURL *url = [NSURL URLWithString:@"http://img.pconline.com.cn/images/photoblog/9/9/8/1/9981681/200910/11/1255259355826.jpg"];
     
        
        // 加载图片
        NSData *data = [NSData dataWithContentsOfURL:url];
        
        // 生成图片
        UIImage *image = [UIImage imageWithData:data];
        
        // 回到主线程
        [[NSOperationQueue mainQueue] addOperationWithBlock:^{
            self.imageView.image = image;
        }];
    }];
}

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

推荐阅读更多精彩内容