接着看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. 前端 CSS 介绍

    CSS介绍 我们为什么需要CSS? 使用css的目的就是让网页具有美观一致的页面,另外一个最重要的原因是内容与格式分离 在没有CSS之前,我们想要修改HTML标签的样式需要为每个HTML标签单独定义样 ...

  2. iOS MJExtension的使用

    前言: MJExtension是iOS的字典装模型的一个第三方框架.相对于JSONKit和SBJson相比MJExtension更简单易用.功能更强大. 安装: 使用CocoaPods导入(Cocoa ...

  3. AIX 7.1 RAC 11.2.0.4.0升级至11.2.0.4.6(一个patch跑了3个小时)

    1.环境 DB:两节点RAC 11.2.0.4.0升级至11.2.0.4.6 OS:AIX 7.1(205G内存 16C) 2.节点1.节点2(未建库) 2.1.patch 20420937居然用了3 ...

  4. 使用AD画PCB的技能总结(纯属个人笔记,请大神多多指导)

    在参加2017全国电子设计大赛的过程中,我将平时学到的点点滴滴记录下来,作为曾经的回忆吧!(未完待续) ------------------------------------------------ ...

  5. python绘制中文词云图

    准备工作 主要用到Python的两个第三方库 jieba:中文分词工具 wordcloud:python下的词云生成工具 步骤 准备语料库,词云图需要的背景图片 使用jieba进行分词,去停用词,词频 ...

  6. 团队项目第一篇——NABCD

    团队名称: 团队项目名称: 团队口号: N(Need)需求: 现如今数据越来越零碎化,繁杂化,身为在校大学生的我们也因此对于时间的利用率也相应减少,为了时间的充分利用,减少在冗杂的信息中耽误的时间,充 ...

  7. CarbonData-1:common

    最近公司需要对CarbonData进一步应用,或许封装进产品,或许是为了解析CarbonData元数据,于是开始预研CarbonData,下面将保持每天一篇以上的阅读CarbonData源码博客,由于 ...

  8. mac下mysql安装及配置启动

    ---恢复内容开始--- 原始链接:https://segmentfault.com/q/1010000000475470 按照如下方法成功安装并启动: mysql.server start//启动服 ...

  9. 监听auduo标签播放

    <audio id="audio" controls="controls" loop="loop" style="displ ...

  10. zabbix监控实战<3> 之自定义监控实例

    第一章    自定义监控tcp状态 命令可以选择ss 或者 netstat    ss打印基于socket的统计信息,实际运行下来,ss的速度要比netstat要快得多 1.1  tcp的十一种状态 ...