接着看NSOperation、NSOperationQueue线程间的通信:

应用场景:比如我们经常把一些耗时的操作比如下载图片放在子线程,那么当这个完成之后,我们就需要回到主线程,这个时候就需要用到线程间的通信。

来看下代码:

//线程间通信
-(void)communication{
//1.创建队列
NSOperationQueue *queue = [[NSOperationQueue alloc] init]; //2.添加操作
[queue addOperationWithBlock:^{
//异步进行的耗时操作
for (int i=0; i<2; ++i) {
[NSThread sleepForTimeInterval:2.0];//模拟耗时操作
NSLog(@"1----%@",[NSThread currentThread]);//打印当前线程
} //回到主线程
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
//进行UI刷新操作
for (int i=0; i<2; ++i) {
[NSThread sleepForTimeInterval:2.0];
NSLog(@"2----%@",[NSThread currentThread]);
}
}];
}];
}

  来看打印:

2019-04-09 11:25:34.507056+0800 MyNSOperation[2488:37353] 1----<NSThread: 0x600000082840>{number = 3, name = (null)}
2019-04-09 11:25:36.510730+0800 MyNSOperation[2488:37353] 1----<NSThread: 0x600000082840>{number = 3, name = (null)}
2019-04-09 11:25:38.513231+0800 MyNSOperation[2488:37047] 2----<NSThread: 0x6000000e29c0>{number = 1, name = main}
2019-04-09 11:25:40.516515+0800 MyNSOperation[2488:37047] 2----<NSThread: 0x6000000e29c0>{number = 1, name = main}

  可以看到,在子线程进行异步操作后,回到了主线程。

再来看下NSOperation与NSOperationQueue的线程同步与线程安全

我们来看一个经典的卖火车票的例子,假如我们不考虑线程安全是啥情况。

/*
非线程安全,不用锁 */
-(void)initTicketStatusNotSafe{
NSLog(@"currentThread---%@",[NSThread currentThread]);
self.ticketCount = 50;
//1.创建queue1,queue1代表北京售票窗口
NSOperationQueue *queue1 = [[NSOperationQueue alloc] init];
queue1.maxConcurrentOperationCount = 1;
//2.创建queue2.queue2代表上海售票窗口
NSOperationQueue *queue2 = [[NSOperationQueue alloc] init];
queue2.maxConcurrentOperationCount = 1;
//3.创建卖票的操作
NSBlockOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{
[self saleTicketNotSafe];
}];
//4.创建卖票操作
NSBlockOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{
[self saleTicketNotSafe];
}]; //5.开始卖票
[queue1 addOperation:op1];
[queue2 addOperation:op2];
} //售卖火车票
-(void)saleTicketNotSafe{
while(true){
if (self.ticketCount>0) {
//如果还有票,就继续卖
self.ticketCount--;
NSLog(@"%@",[NSString stringWithFormat:@"剩余票数:%d 窗口%@",self.ticketCount,[NSThread currentThread]]);
[NSThread sleepForTimeInterval:2.0];
}else{
NSLog(@"所有的火车票已售完");
break;
}
}
}

  看打印情况:

2019-04-09 11:57:13.000691+0800 MyNSOperation[3785:58834] currentThread---<NSThread: 0x600002ad1240>{number = 1, name = main}
2019-04-09 11:57:13.006247+0800 MyNSOperation[3785:58934] 剩余票数:49 窗口<NSThread: 0x600002a87c00>{number = 3, name = (null)}
2019-04-09 11:57:13.006501+0800 MyNSOperation[3785:58932] 剩余票数:48 窗口<NSThread: 0x600002ab8040>{number = 4, name = (null)}
2019-04-09 11:57:15.011866+0800 MyNSOperation[3785:58934] 剩余票数:47 窗口<NSThread: 0x600002a87c00>{number = 3, name = (null)}
2019-04-09 11:57:15.011959+0800 MyNSOperation[3785:58932] 剩余票数:46 窗口<NSThread: 0x600002ab8040>{number = 4, name = (null)}
2019-04-09 11:57:17.015980+0800 MyNSOperation[3785:58934] 剩余票数:45 窗口<NSThread: 0x600002a87c00>{number = 3, name = (null)}
2019-04-09 11:57:17.015980+0800 MyNSOperation[3785:58932] 剩余票数:45 窗口<NSThread: 0x600002ab8040>{number = 4, name = (null)}
2019-04-09 11:57:19.020346+0800 MyNSOperation[3785:58934] 剩余票数:43 窗口<NSThread: 0x600002a87c00>{number = 3, name = (null)}
2019-04-09 11:57:19.020354+0800 MyNSOperation[3785:58932] 剩余票数:44 窗口<NSThread: 0x600002ab8040>{number = 4, name = (null)}
2019-04-09 11:57:21.026026+0800 MyNSOperation[3785:58934] 剩余票数:42 窗口<NSThread: 0x600002a87c00>{number = 3, name = (null)}
2019-04-09 11:57:21.026112+0800 MyNSOperation[3785:58932] 剩余票数:41 窗口<NSThread: 0x600002ab8040>{number = 4, name = (null)}
2019-04-09 11:57:23.026638+0800 MyNSOperation[3785:58934] 剩余票数:39 窗口<NSThread: 0x600002a87c00>{number = 3, name = (null)}
2019-04-09 11:57:23.026648+0800 MyNSOperation[3785:58932] 剩余票数:40 窗口<NSThread: 0x600002ab8040>{number = 4, name = (null)}
2019-04-09 11:57:25.031698+0800 MyNSOperation[3785:58934] 剩余票数:38 窗口<NSThread: 0x600002a87c00>{number = 3, name = (null)}
2019-04-09 11:57:25.031763+0800 MyNSOperation[3785:58932] 剩余票数:37 窗口<NSThread: 0x600002ab8040>{number = 4, name = (null)}
2019-04-09 11:57:27.032664+0800 MyNSOperation[3785:58934] 剩余票数:36 窗口<NSThread: 0x600002a87c00>{number = 3, name = (null)}
2019-04-09 11:57:27.032664+0800 MyNSOperation[3785:58932] 剩余票数:35 窗口<NSThread: 0x600002ab8040>{number = 4, name = (null)}
2019-04-09 11:57:29.036969+0800 MyNSOperation[3785:58934] 剩余票数:34 窗口<NSThread: 0x600002a87c00>{number = 3, name = (null)}
2019-04-09 11:57:29.037052+0800 MyNSOperation[3785:58932] 剩余票数:33 窗口<NSThread: 0x600002ab8040>{number = 4, name = (null)}
2019-04-09 11:57:31.041413+0800 MyNSOperation[3785:58934] 剩余票数:31 窗口<NSThread: 0x600002a87c00>{number = 3, name = (null)}
2019-04-09 11:57:31.041416+0800 MyNSOperation[3785:58932] 剩余票数:32 窗口<NSThread: 0x600002ab8040>{number = 4, name = (null)}
2019-04-09 11:57:33.044314+0800 MyNSOperation[3785:58934] 剩余票数:30 窗口<NSThread: 0x600002a87c00>{number = 3, name = (null)}
2019-04-09 11:57:33.044314+0800 MyNSOperation[3785:58932] 剩余票数:29 窗口<NSThread: 0x600002ab8040>{number = 4, name = (null)}
2019-04-09 11:57:35.049399+0800 MyNSOperation[3785:58934] 剩余票数:28 窗口<NSThread: 0x600002a87c00>{number = 3, name = (null)}
2019-04-09 11:57:35.049449+0800 MyNSOperation[3785:58932] 剩余票数:28 窗口<NSThread: 0x600002ab8040>{number = 4, name = (null)}
2019-04-09 11:57:37.054456+0800 MyNSOperation[3785:58934] 剩余票数:27 窗口<NSThread: 0x600002a87c00>{number = 3, name = (null)}
2019-04-09 11:57:37.054456+0800 MyNSOperation[3785:58932] 剩余票数:27 窗口<NSThread: 0x600002ab8040>{number = 4, name = (null)}
2019-04-09 11:57:39.057780+0800 MyNSOperation[3785:58934] 剩余票数:26 窗口<NSThread: 0x600002a87c00>{number = 3, name = (null)}
2019-04-09 11:57:39.057780+0800 MyNSOperation[3785:58932] 剩余票数:26 窗口<NSThread: 0x600002ab8040>{number = 4, name = (null)}
2019-04-09 11:57:41.058922+0800 MyNSOperation[3785:58932] 剩余票数:25 窗口<NSThread: 0x600002ab8040>{number = 4, name = (null)}
2019-04-09 11:57:41.058922+0800 MyNSOperation[3785:58934] 剩余票数:25 窗口<NSThread: 0x600002a87c00>{number = 3, name = (null)}
2019-04-09 11:57:43.062224+0800 MyNSOperation[3785:58932] 剩余票数:24 窗口<NSThread: 0x600002ab8040>{number = 4, name = (null)}
2019-04-09 11:57:43.062312+0800 MyNSOperation[3785:58934] 剩余票数:23 窗口<NSThread: 0x600002a87c00>{number = 3, name = (null)}
2019-04-09 11:57:45.066320+0800 MyNSOperation[3785:58934] 剩余票数:21 窗口<NSThread: 0x600002a87c00>{number = 3, name = (null)}
2019-04-09 11:57:45.066320+0800 MyNSOperation[3785:58932] 剩余票数:22 窗口<NSThread: 0x600002ab8040>{number = 4, name = (null)}
2019-04-09 11:57:47.070458+0800 MyNSOperation[3785:58934] 剩余票数:20 窗口<NSThread: 0x600002a87c00>{number = 3, name = (null)}
2019-04-09 11:57:47.070470+0800 MyNSOperation[3785:58932] 剩余票数:20 窗口<NSThread: 0x600002ab8040>{number = 4, name = (null)}
2019-04-09 11:57:49.072585+0800 MyNSOperation[3785:58934] 剩余票数:19 窗口<NSThread: 0x600002a87c00>{number = 3, name = (null)}
2019-04-09 11:57:49.072585+0800 MyNSOperation[3785:58932] 剩余票数:18 窗口<NSThread: 0x600002ab8040>{number = 4, name = (null)}
2019-04-09 11:57:51.076732+0800 MyNSOperation[3785:58934] 剩余票数:17 窗口<NSThread: 0x600002a87c00>{number = 3, name = (null)}
2019-04-09 11:57:51.076732+0800 MyNSOperation[3785:58932] 剩余票数:16 窗口<NSThread: 0x600002ab8040>{number = 4, name = (null)}
2019-04-09 11:57:53.081887+0800 MyNSOperation[3785:58932] 剩余票数:15 窗口<NSThread: 0x600002ab8040>{number = 4, name = (null)}
2019-04-09 11:57:53.081887+0800 MyNSOperation[3785:58934] 剩余票数:15 窗口<NSThread: 0x600002a87c00>{number = 3, name = (null)}
2019-04-09 11:57:55.084748+0800 MyNSOperation[3785:58934] 剩余票数:14 窗口<NSThread: 0x600002a87c00>{number = 3, name = (null)}
2019-04-09 11:57:55.084752+0800 MyNSOperation[3785:58932] 剩余票数:13 窗口<NSThread: 0x600002ab8040>{number = 4, name = (null)}
2019-04-09 11:57:57.087508+0800 MyNSOperation[3785:58934] 剩余票数:11 窗口<NSThread: 0x600002a87c00>{number = 3, name = (null)}
2019-04-09 11:57:57.087508+0800 MyNSOperation[3785:58932] 剩余票数:12 窗口<NSThread: 0x600002ab8040>{number = 4, name = (null)}
2019-04-09 11:57:59.092573+0800 MyNSOperation[3785:58932] 剩余票数:10 窗口<NSThread: 0x600002ab8040>{number = 4, name = (null)}
2019-04-09 11:57:59.092573+0800 MyNSOperation[3785:58934] 剩余票数:10 窗口<NSThread: 0x600002a87c00>{number = 3, name = (null)}
2019-04-09 11:58:01.096928+0800 MyNSOperation[3785:58934] 剩余票数:8 窗口<NSThread: 0x600002a87c00>{number = 3, name = (null)}
2019-04-09 11:58:01.096928+0800 MyNSOperation[3785:58932] 剩余票数:9 窗口<NSThread: 0x600002ab8040>{number = 4, name = (null)}
2019-04-09 11:58:03.102158+0800 MyNSOperation[3785:58934] 剩余票数:6 窗口<NSThread: 0x600002a87c00>{number = 3, name = (null)}
2019-04-09 11:58:03.102075+0800 MyNSOperation[3785:58932] 剩余票数:7 窗口<NSThread: 0x600002ab8040>{number = 4, name = (null)}
2019-04-09 11:58:05.106820+0800 MyNSOperation[3785:58934] 剩余票数:5 窗口<NSThread: 0x600002a87c00>{number = 3, name = (null)}
2019-04-09 11:58:05.106821+0800 MyNSOperation[3785:58932] 剩余票数:4 窗口<NSThread: 0x600002ab8040>{number = 4, name = (null)}
2019-04-09 11:58:07.110551+0800 MyNSOperation[3785:58932] 剩余票数:3 窗口<NSThread: 0x600002ab8040>{number = 4, name = (null)}
2019-04-09 11:58:07.110571+0800 MyNSOperation[3785:58934] 剩余票数:3 窗口<NSThread: 0x600002a87c00>{number = 3, name = (null)}
2019-04-09 11:58:09.115589+0800 MyNSOperation[3785:58932] 剩余票数:1 窗口<NSThread: 0x600002ab8040>{number = 4, name = (null)}
2019-04-09 11:58:09.115589+0800 MyNSOperation[3785:58934] 剩余票数:2 窗口<NSThread: 0x600002a87c00>{number = 3, name = (null)}
2019-04-09 11:58:11.117467+0800 MyNSOperation[3785:58932] 所有的火车票已售完
2019-04-09 11:58:11.117476+0800 MyNSOperation[3785:58934] 剩余票数:0 窗口<NSThread: 0x600002a87c00>{number = 3, name = (null)}
2019-04-09 11:58:13.120972+0800 MyNSOperation[3785:58934] 所有的火车票已售完

  可以看到,有多个票数得到的是重复的,错乱的。

所有我们要解决线程安全的问题,使用锁。在一个线程操作一个资源的时候,给这个资源加锁,不允许其他线程进行操作。IOS中实现线程加锁的方式是有很多种的。比如@synchronized,NSLock,NSRecursiveLock,NSConditionLock等等多种方式。我们这里使用NSLock的方式来给线程加锁。

我们来看下使用线程安全的代码:

/*
线程安全的代码,使用NSLock锁
初始化火车票数量,卖票窗口(线程安全),并开始卖票
*/
-(void)initTicketStatusSafe{
NSLog(@"currentThread----%@",[NSThread currentThread]);
self.ticketCount = 50;
self.lock = [[NSLock alloc] init];
//1.创建queue1,queue1代表北京售票窗口
NSOperationQueue *queue1 = [[NSOperationQueue alloc] init];
queue1.maxConcurrentOperationCount = 1; //2.创建queue2,queue2代表上海售票窗口
NSOperationQueue *queue2 = [[NSOperationQueue alloc] init];
queue2.maxConcurrentOperationCount = 1; //3.创建卖票操作op1
NSBlockOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{
[self saleTicketSafe];
}];
//4.创建卖票操作op2
NSBlockOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{
[self saleTicketSafe];
}];
//5.添加操作,开始卖票
[queue1 addOperation:op1];
[queue2 addOperation:op2];
} //售卖火车票(线程安全)
-(void)saleTicketSafe{
while (true) {
//加锁
[self.lock lock];
if(self.ticketCount>0){
//如果还有票的话,就继续卖票
self.ticketCount--;
NSLog(@"%@",[NSString stringWithFormat:@"剩余票数:%d,窗口:%@",self.ticketCount,[NSThread currentThread]]);
[NSThread sleepForTimeInterval:2.0];
}
//解锁
[self.lock unlock];
if(self.ticketCount<=0){
NSLog(@"所有票已经卖完");
break;
}
}
}

  来看打印:

2019-04-09 15:29:44.182861+0800 MyNSOperation[10565:159368] currentThread----<NSThread: 0x60000063f780>{number = 1, name = main}
2019-04-09 15:29:44.186854+0800 MyNSOperation[10565:159459] 剩余票数:49,窗口:<NSThread: 0x600000663740>{number = 3, name = (null)}
2019-04-09 15:29:46.187749+0800 MyNSOperation[10565:159449] 剩余票数:48,窗口:<NSThread: 0x600000658bc0>{number = 4, name = (null)}
2019-04-09 15:29:48.190175+0800 MyNSOperation[10565:159459] 剩余票数:47,窗口:<NSThread: 0x600000663740>{number = 3, name = (null)}
2019-04-09 15:29:50.193962+0800 MyNSOperation[10565:159449] 剩余票数:46,窗口:<NSThread: 0x600000658bc0>{number = 4, name = (null)}
2019-04-09 15:29:52.199454+0800 MyNSOperation[10565:159459] 剩余票数:45,窗口:<NSThread: 0x600000663740>{number = 3, name = (null)}
2019-04-09 15:29:54.203206+0800 MyNSOperation[10565:159449] 剩余票数:44,窗口:<NSThread: 0x600000658bc0>{number = 4, name = (null)}
2019-04-09 15:29:56.207794+0800 MyNSOperation[10565:159459] 剩余票数:43,窗口:<NSThread: 0x600000663740>{number = 3, name = (null)}
2019-04-09 15:29:58.213412+0800 MyNSOperation[10565:159449] 剩余票数:42,窗口:<NSThread: 0x600000658bc0>{number = 4, name = (null)}
2019-04-09 15:30:00.214024+0800 MyNSOperation[10565:159459] 剩余票数:41,窗口:<NSThread: 0x600000663740>{number = 3, name = (null)}
2019-04-09 15:30:02.219388+0800 MyNSOperation[10565:159449] 剩余票数:40,窗口:<NSThread: 0x600000658bc0>{number = 4, name = (null)}
2019-04-09 15:30:04.224701+0800 MyNSOperation[10565:159459] 剩余票数:39,窗口:<NSThread: 0x600000663740>{number = 3, name = (null)}
2019-04-09 15:30:06.230349+0800 MyNSOperation[10565:159449] 剩余票数:38,窗口:<NSThread: 0x600000658bc0>{number = 4, name = (null)}
2019-04-09 15:30:08.233439+0800 MyNSOperation[10565:159459] 剩余票数:37,窗口:<NSThread: 0x600000663740>{number = 3, name = (null)}
2019-04-09 15:30:10.236390+0800 MyNSOperation[10565:159449] 剩余票数:36,窗口:<NSThread: 0x600000658bc0>{number = 4, name = (null)}
2019-04-09 15:30:12.239285+0800 MyNSOperation[10565:159459] 剩余票数:35,窗口:<NSThread: 0x600000663740>{number = 3, name = (null)}
2019-04-09 15:30:14.242919+0800 MyNSOperation[10565:159449] 剩余票数:34,窗口:<NSThread: 0x600000658bc0>{number = 4, name = (null)}
2019-04-09 15:30:16.246876+0800 MyNSOperation[10565:159459] 剩余票数:33,窗口:<NSThread: 0x600000663740>{number = 3, name = (null)}
2019-04-09 15:30:18.252321+0800 MyNSOperation[10565:159449] 剩余票数:32,窗口:<NSThread: 0x600000658bc0>{number = 4, name = (null)}
2019-04-09 15:30:20.253964+0800 MyNSOperation[10565:159459] 剩余票数:31,窗口:<NSThread: 0x600000663740>{number = 3, name = (null)}
2019-04-09 15:30:22.254687+0800 MyNSOperation[10565:159449] 剩余票数:30,窗口:<NSThread: 0x600000658bc0>{number = 4, name = (null)}
2019-04-09 15:30:24.255193+0800 MyNSOperation[10565:159459] 剩余票数:29,窗口:<NSThread: 0x600000663740>{number = 3, name = (null)}
2019-04-09 15:30:26.256679+0800 MyNSOperation[10565:159449] 剩余票数:28,窗口:<NSThread: 0x600000658bc0>{number = 4, name = (null)}
2019-04-09 15:30:28.261450+0800 MyNSOperation[10565:159459] 剩余票数:27,窗口:<NSThread: 0x600000663740>{number = 3, name = (null)}
2019-04-09 15:30:30.262594+0800 MyNSOperation[10565:159449] 剩余票数:26,窗口:<NSThread: 0x600000658bc0>{number = 4, name = (null)}
2019-04-09 15:30:32.267232+0800 MyNSOperation[10565:159459] 剩余票数:25,窗口:<NSThread: 0x600000663740>{number = 3, name = (null)}
2019-04-09 15:30:34.271705+0800 MyNSOperation[10565:159449] 剩余票数:24,窗口:<NSThread: 0x600000658bc0>{number = 4, name = (null)}
2019-04-09 15:30:36.275290+0800 MyNSOperation[10565:159459] 剩余票数:23,窗口:<NSThread: 0x600000663740>{number = 3, name = (null)}
2019-04-09 15:30:38.278967+0800 MyNSOperation[10565:159449] 剩余票数:22,窗口:<NSThread: 0x600000658bc0>{number = 4, name = (null)}
2019-04-09 15:30:40.284568+0800 MyNSOperation[10565:159459] 剩余票数:21,窗口:<NSThread: 0x600000663740>{number = 3, name = (null)}
2019-04-09 15:30:42.288319+0800 MyNSOperation[10565:159449] 剩余票数:20,窗口:<NSThread: 0x600000658bc0>{number = 4, name = (null)}
2019-04-09 15:30:44.293916+0800 MyNSOperation[10565:159459] 剩余票数:19,窗口:<NSThread: 0x600000663740>{number = 3, name = (null)}
2019-04-09 15:30:46.298411+0800 MyNSOperation[10565:159449] 剩余票数:18,窗口:<NSThread: 0x600000658bc0>{number = 4, name = (null)}
2019-04-09 15:30:48.301898+0800 MyNSOperation[10565:159459] 剩余票数:17,窗口:<NSThread: 0x600000663740>{number = 3, name = (null)}
2019-04-09 15:30:50.307369+0800 MyNSOperation[10565:159449] 剩余票数:16,窗口:<NSThread: 0x600000658bc0>{number = 4, name = (null)}
2019-04-09 15:30:52.309734+0800 MyNSOperation[10565:159459] 剩余票数:15,窗口:<NSThread: 0x600000663740>{number = 3, name = (null)}
2019-04-09 15:30:54.312124+0800 MyNSOperation[10565:159449] 剩余票数:14,窗口:<NSThread: 0x600000658bc0>{number = 4, name = (null)}
2019-04-09 15:30:56.313696+0800 MyNSOperation[10565:159459] 剩余票数:13,窗口:<NSThread: 0x600000663740>{number = 3, name = (null)}
2019-04-09 15:30:58.315219+0800 MyNSOperation[10565:159449] 剩余票数:12,窗口:<NSThread: 0x600000658bc0>{number = 4, name = (null)}
2019-04-09 15:31:00.317869+0800 MyNSOperation[10565:159459] 剩余票数:11,窗口:<NSThread: 0x600000663740>{number = 3, name = (null)}
2019-04-09 15:31:02.322281+0800 MyNSOperation[10565:159449] 剩余票数:10,窗口:<NSThread: 0x600000658bc0>{number = 4, name = (null)}
2019-04-09 15:31:04.326708+0800 MyNSOperation[10565:159459] 剩余票数:9,窗口:<NSThread: 0x600000663740>{number = 3, name = (null)}
2019-04-09 15:31:06.332550+0800 MyNSOperation[10565:159449] 剩余票数:8,窗口:<NSThread: 0x600000658bc0>{number = 4, name = (null)}
2019-04-09 15:31:08.336064+0800 MyNSOperation[10565:159459] 剩余票数:7,窗口:<NSThread: 0x600000663740>{number = 3, name = (null)}
2019-04-09 15:31:10.341717+0800 MyNSOperation[10565:159449] 剩余票数:6,窗口:<NSThread: 0x600000658bc0>{number = 4, name = (null)}
2019-04-09 15:31:12.342312+0800 MyNSOperation[10565:159459] 剩余票数:5,窗口:<NSThread: 0x600000663740>{number = 3, name = (null)}
2019-04-09 15:31:14.347439+0800 MyNSOperation[10565:159449] 剩余票数:4,窗口:<NSThread: 0x600000658bc0>{number = 4, name = (null)}
2019-04-09 15:31:16.348122+0800 MyNSOperation[10565:159459] 剩余票数:3,窗口:<NSThread: 0x600000663740>{number = 3, name = (null)}
2019-04-09 15:31:18.352838+0800 MyNSOperation[10565:159449] 剩余票数:2,窗口:<NSThread: 0x600000658bc0>{number = 4, name = (null)}
2019-04-09 15:31:20.355310+0800 MyNSOperation[10565:159459] 剩余票数:1,窗口:<NSThread: 0x600000663740>{number = 3, name = (null)}
2019-04-09 15:31:22.358857+0800 MyNSOperation[10565:159449] 剩余票数:0,窗口:<NSThread: 0x600000658bc0>{number = 4, name = (null)}
2019-04-09 15:31:24.363256+0800 MyNSOperation[10565:159449] 所有票已经卖完
2019-04-09 15:31:24.363263+0800 MyNSOperation[10565:159459] 所有票已经卖完

  可以看出,在使用了线程安全机制之后,票数正常了。

IOS高级开发之多线程(五)NSOperation 2的更多相关文章

  1. IOS高级开发之多线程(四)NSOperation

    1.什么是NSOperation,NSOperationQueue? NSOperation是一个抽象的基类,表示一个独立的计算单元,可以为子类提供有用且线程安全的建立状态,优先级,依赖和取消等操作. ...

  2. ios高级开发之多线程(三)GCD技术

    GCD是基于C的API,它是libdispatch的的市场名称.而libdispatch作为Apple公司的一个库,为并发代码在多核硬件(跑IOS或者OS X)上执行提供有力支持. 那么我们为什么要用 ...

  3. ios高级开发之多线程(二)NSThread技术

    多线程技术是有多套解决方案的,那么我们该如何选择呢? 技术方案 简介 语言 线程生命周期 使用频率 pthread 1.一套通用的多线程API 2.适用于UNIX,linux,windows等 3.跨 ...

  4. ios高级开发之多线程(一)

    1.概念: 多线程(multithreading)到底是什么呢,它是指在软件或者硬件上实现多个线程并发执行的技术.具有多线程能力的计算机因有硬件的支持,而能够在同一时间执行多个线程,进而提升整体处理性 ...

  5. 移动开发在路上-- IOS移动开发系列 多线程二

    最近太忙没太多的时间,忙碌的码农生活空下来一点时间,都会挤出来看一些技术或者咨询的文章,废话不多说,直奔主题. 接着上一次的继续说. 定时器在多线程的使用 NSRunLoop 是线程相关的基础框架的一 ...

  6. iOS 11开发教程(五)iOS11模拟器介绍二

    iOS 11开发教程(五)iOS11模拟器介绍二 3.iOS11模拟器中设置语言 对于不同国家的人来说,使用到的语言是不一样的.一般情况下iOS11模拟器默认使用的English(英语).对于英文不好 ...

  7. (转发)IOS高级开发~Runtime(四)

    用C代替OC: #import <objc/runtime.h> #import <objc/message.h> #import <stdio.h> extern ...

  8. (转发)IOS高级开发~Runtime(三)

    11.系统类的方法实现部分替换 - (void) methodExchange { Method m1 = class_getInstanceMethod([NSStringclass],@selec ...

  9. (转发)IOS高级开发~Runtime(二)

    一些公用类: @interface ClassCustomClass :NSObject{ NSString *varTest1; NSString *varTest2; NSString *varT ...

随机推荐

  1. 【window】mongodb安装和配置

    最近要独立开发vue+mongodb+node的小项目,项目不大,但之前没了解过mongodb还是蛮不容易的,因为以前用MySQL的时候都是用的集成化的工具,完全不用写命令去启动,用mogodb首先需 ...

  2. Openshift 错误解决 "修改docker cgroup driver"

    一.Openshift 错误解决 "修改docker cgroup driver" 一.错误如下 failed to run Kubelet: failed to create k ...

  3. PHP知识点

    目录 1. PHP函数前面添加@的作用 2. PHP连接MySQL数据库字符集设置 1. 通过PDO扩展连接MySQL数据库 2. 通过mysql扩展连接 3. php查询数据库出现中文乱码 3. 参 ...

  4. session 和 cookie

    在web请求中,很多的时候服务器需要知道来访的客户是谁,但是HTTP协议本身是不带认证的(ftp协议需要用户密码),因此cookie和session诞生了.   session是解决http协议无状态 ...

  5. carbondata-summary

    源码 http://www.zhuyongpeng.cn/1699.html 融合数据白皮书:Apache CarbonData成为主流融合存储技术 http://cloud.yesky.com/46 ...

  6. UnzipUtil

    public class UnzipUtil { private static final Logger logger = LoggerFactory.getLogger(CopyFileUtil.c ...

  7. Python练习:小程序,列车出票程序

    # 需求:列车某结车厢座位有15行,5列,初始状态均为'有票',当乘客选了座次,下单后,变更为'已售' # 下单时,要显示所有座位的状态(有票or已售) # 下单完毕后,显示下单后的座位状态. lin ...

  8. (3)打造简单OS-MBR引导区转移加载简单程序(突破512限制)

    在第一节<(1)汇编写入引导区,虚拟机启动步骤>中讲解到一个简单屏幕显示一川字符串,第二节讲到BIOS启动过程! 第一节中基本原理就是将那个汇编代码用nasm汇编器进行汇编成二进制,然后把 ...

  9. 移动App专项测试

    移动App测试实战—专项测试 转自:http://www.51testing.com/html/58/n-3713758.html 我们在进行了手工的功能测试之后,也开发了一些自动化测试用例,并且做了 ...

  10. 2018.2.22 学习笔记 random模块及每日一练

    给你一个字符数,把它的每个字符之间加上一个空格,形成一个新字符串. 例如:I love FishC.  变成I   l o v e   F i s h C . 跟小甲鱼学编程 变成 跟 小 甲 鱼 学 ...