接着看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. SpringBoot单元测试

    一.Service层Junit单元测试 需要的jar包 <dependency> <groupId>org.springframework.boot</groupId&g ...

  2. linux echo 命令 打印字符串

    打印字符串 [root@MongoDB ~]# echo "heloworld" heloworld

  3. 好用的一些 git 命令

    git stash  将已修改未提交的 改动保存起来   恢复用git stash pop gir revert  反转commit git rebase 更换基础分支 git grep  -n 显示 ...

  4. MATLAB算术运算符和常用函数

    1 算术运算符 Matlab中的算术运算符按优先级由高到低为: (1) ^           幂 (2) *            乘      /            右除(正常除)       ...

  5. GAITC 2019全球人工智能技术大会(南京)

    2019年5月25日至26日,由中国人工智能学会主办,以“交叉.融合.相生.共赢”为主题的2019GAITC将在南京全新亮相. 2019 全球人工智能技术大会(2019 GAITC)以“前端引领.深度 ...

  6. Aliyun OSS Nginx proxy module(阿里云OSS Nginx 签名代理模块)

    1.此文章主要介绍内容 本文主要介绍如何利用Nginx lua 实现将阿里云OSS存储空间做到同本地磁盘一样使用.核心是利用Nginx lua 对OSS请求进行签名并利用内部跳转将所有访问本地Ngin ...

  7. static 关键字的作用

    在C语言中,关键字static有三个明显的作用: 1)在函数体内,一个被声明为静态的变量在这一函数被调用过程中维持其值不变(该变量存放在静态变量区). 2) 在模块内(但在函数体外),一个被声明为静态 ...

  8. python值json与pickle模块

    #json 是用来序列化对象的 # 只有2个方法,序列化与反序列化 # 但是不能序列化类 与 函数 import json dict={"key1":[1,2,3,4,5]} f ...

  9. CentOS 7 Squid代理服务器正向代理-传统代理

    Squid是Linux系统中最常用的一款开源代理服务软件,主要提供缓存加速和应用层过滤控制的功能,可以很好的实现HTTP.FTP.DNS查询以及SSL等应用的缓存代理 传统代理:普通的代理服务,多见于 ...

  10. document.wrtie()用法

    推荐看这篇文章,非常的好 http://www.softwhy.com/article-8326-1.html