NSThread
如何用?
- (void)nsthreadDemo {
//创建方法
//1 动态创建 需要调用start启动线程
NSThread *thread1 = [[NSThread alloc] initWithTarget:self selector:@selector(threadMethod) object:nil];
thread1.name = @"我是线程1售票窗口";
//2 静态创建 没有返回值 如果需要获取到用这个方法创建的线程 需要在selector中通过currentThread获取
// [NSThread detachNewThreadSelector:@selector(threadMethod) toTarget:self withObject:nil];
NSThread *thread2 = [[NSThread alloc] initWithTarget:self selector:@selector(threadMethod) object:nil];
thread2.name = @"我是线程2售票窗口";
NSThread *thread3 = [[NSThread alloc] initWithTarget:self selector:@selector(threadMethod) object:nil];
thread3.name = @"我是线程3售票窗口";
//设置线程优先级
// NSQualityOfServiceUserInteractive:最高优先级,用于用户交互事件
// NSQualityOfServiceUserInitiated:次高优先级,用于用户需要马上执行的事件
// NSQualityOfServiceDefault:默认优先级,主线程和没有设置优先级的线程都默认为这个优先级
// NSQualityOfServiceUtility:普通优先级,用于普通任务
// NSQualityOfServiceBackground:最低优先级,用于不重要的任务
// [thread1 setQualityOfService:NSQualityOfServiceUserInteractive];
//线程开启
[thread1 start];
[thread2 start];
[thread3 start];
//线程通信
//在主线程中执行
// [self performSelectorOnMainThread:@selector(mainThreadMethod) withObject:nil waitUntilDone:YES];
//开辟一条线程执行
// [self performSelectorInBackground:@selector(threadMethod) withObject:nil];
//在当前线程执行
// [self performSelector:@selector(threadMethod)];
// [self performSelector:@selector(threadMethod) withObject:nil];
// [self performSelector:@selector(threadMethod) withObject:nil afterDelay:2.0];//在当前线程延时执行
//在指定线程中执行
// [self performSelector:@selector(threadMethod) onThread:thread1 withObject:nil waitUntilDone:YES];
}
- (void)threadMethod {
//线程暂停
// [NSThread sleepForTimeInterval:1.0];
// [NSThread sleepUntilDate:[NSDate dateWithTimeIntervalSinceNow:1.0]];
//线程取消 只是标记线程是否需要退出 并不会马上停止和退出线程
// [[NSThread currentThread] cancel];
//线程退出
// [NSThread exit];
// NSLog(@"当前线程:%@",[NSThread currentThread]);
//线程同步
/*
如上篇GCD同步问题描述,我们现在解决一个售票问题,假如有二十张票,同时三个窗口在售卖。我们先看看直接三个线程访问这个票源会出现什么问题。
*/
while (1) {
@synchronized(self) {
if (tickCount > 0) {
tickCount--; //模拟卖出一张票
NSLog(@"当前线程:%@ 剩余票数%d",[NSThread currentThread],tickCount);
[NSThread sleepForTimeInterval:1.2];
}else {
NSLog(@"销售完毕");
break;
}
}
}
}
处理线程同步问题:
如果不给会竞争资源的地方加锁
1.如果资源操作不耗时
票数不会错乱,但是会存在两个或多个线程同一时间访问同一张票
2.资源操作耗时
票数错乱。并且存在两个或多个线程同一时间访问同一张票
当前线程:<NSThread: 0x604000271700>{number = 3, name = 我是线程1售票窗口} 剩余票数19
2018-04-08 11:29:17.911633+0800 OC基础[34398:8677737] 当前线程:<NSThread: 0x604000271400>{number = 4, name = 我是线程2售票窗口} 剩余票数18
2018-04-08 11:29:17.911753+0800 OC基础[34398:8677738] 当前线程:<NSThread: 0x604000271640>{number = 5, name = 我是线程3售票窗口} 剩余票数17
2018-04-08 11:29:18.016563+0800 OC基础[34398:8677736] 当前线程:<NSThread: 0x604000271700>{number = 3, name = 我是线程1售票窗口} 剩余票数16
2018-04-08 11:29:18.016665+0800 OC基础[34398:8677737] 当前线程:<NSThread: 0x604000271400>{number = 4, name = 我是线程2售票窗口} 剩余票数15
2018-04-08 11:29:18.017573+0800 OC基础[34398:8677738] 当前线程:<NSThread: 0x604000271640>{number = 5, name = 我是线程3售票窗口} 剩余票数14
2018-04-08 11:29:18.122791+0800 OC基础[34398:8677736] 当前线程:<NSThread: 0x604000271700>{number = 3, name = 我是线程1售票窗口} 剩余票数13
2018-04-08 11:29:18.122875+0800 OC基础[34398:8677738] 当前线程:<NSThread: 0x604000271640>{number = 5, name = 我是线程3售票窗口} 剩余票数11
2018-04-08 11:29:18.122929+0800 OC基础[34398:8677737] 当前线程:<NSThread: 0x604000271400>{number = 4, name = 我是线程2售票窗口} 剩余票数12
2018-04-08 11:29:18.228322+0800 OC基础[34398:8677736] 当前线程:<NSThread: 0x604000271700>{number = 3, name = 我是线程1售票窗口} 剩余票数9
2018-04-08 11:29:18.228322+0800 OC基础[34398:8677738] 当前线程:<NSThread: 0x604000271640>{number = 5, name = 我是线程3售票窗口} 剩余票数9
2018-04-08 11:29:18.228322+0800 OC基础[34398:8677737] 当前线程:<NSThread: 0x604000271400>{number = 4, name = 我是线程2售票窗口} 剩余票数9
2018-04-08 11:29:18.332442+0800 OC基础[34398:8677738] 当前线程:<NSThread: 0x604000271640>{number = 5, name = 我是线程3售票窗口} 剩余票数8
2018-04-08 11:29:18.332512+0800 OC基础[34398:8677736] 当前线程:<NSThread: 0x604000271700>{number = 3, name = 我是线程1售票窗口} 剩余票数7
2018-04-08 11:29:18.332607+0800 OC基础[34398:8677737] 当前线程:<NSThread: 0x604000271400>{number = 4, name = 我是线程2售票窗口} 剩余票数6
2018-04-08 11:29:18.436135+0800 OC基础[34398:8677736] 当前线程:<NSThread: 0x604000271700>{number = 3, name = 我是线程1售票窗口} 剩余票数5
2018-04-08 11:29:18.437151+0800 OC基础[34398:8677738] 当前线程:<NSThread: 0x604000271640>{number = 5, name = 我是线程3售票窗口} 剩余票数4
2018-04-08 11:29:18.437151+0800 OC基础[34398:8677737] 当前线程:<NSThread: 0x604000271400>{number = 4, name = 我是线程2售票窗口} 剩余票数3
2018-04-08 11:29:18.540461+0800 OC基础[34398:8677736] 当前线程:<NSThread: 0x604000271700>{number = 3, name = 我是线程1售票窗口} 剩余票数2
2018-04-08 11:29:18.542040+0800 OC基础[34398:8677738] 当前线程:<NSThread: 0x604000271640>{number = 5, name = 我是线程3售票窗口} 剩余票数0
2018-04-08 11:29:18.542087+0800 OC基础[34398:8677737] 当前线程:<NSThread: 0x604000271400>{number = 4, name = 我是线程2售票窗口} 剩余票数0
以上是资源耗时较少的情况。资源耗时多的情况请自行测试。
加锁后:
当前线程:<NSThread: 0x60000046c4c0>{number = 3, name = 我是线程1售票窗口} 剩余票数19
2018-04-12 10:00:16.688413+0800 OC基础[87234:11885173] 当前线程:<NSThread: 0x60000046c500>{number = 4, name = 我是线程2售票窗口} 剩余票数18
2018-04-12 10:00:17.888849+0800 OC基础[87234:11885174] 当前线程:<NSThread: 0x60000046c0c0>{number = 5, name = 我是线程3售票窗口} 剩余票数17
2018-04-12 10:00:19.092933+0800 OC基础[87234:11885172] 当前线程:<NSThread: 0x60000046c4c0>{number = 3, name = 我是线程1售票窗口} 剩余票数16
2018-04-12 10:00:20.298277+0800 OC基础[87234:11885173] 当前线程:<NSThread: 0x60000046c500>{number = 4, name = 我是线程2售票窗口} 剩余票数15
2018-04-12 10:00:21.499725+0800 OC基础[87234:11885174] 当前线程:<NSThread: 0x60000046c0c0>{number = 5, name = 我是线程3售票窗口} 剩余票数14
2018-04-12 10:00:22.703571+0800 OC基础[87234:11885172] 当前线程:<NSThread: 0x60000046c4c0>{number = 3, name = 我是线程1售票窗口} 剩余票数13
2018-04-12 10:00:23.907196+0800 OC基础[87234:11885173] 当前线程:<NSThread: 0x60000046c500>{number = 4, name = 我是线程2售票窗口} 剩余票数12
2018-04-12 10:00:25.109659+0800 OC基础[87234:11885174] 当前线程:<NSThread: 0x60000046c0c0>{number = 5, name = 我是线程3售票窗口} 剩余票数11
2018-04-12 10:00:26.312094+0800 OC基础[87234:11885172] 当前线程:<NSThread: 0x60000046c4c0>{number = 3, name = 我是线程1售票窗口} 剩余票数10
2018-04-12 10:00:27.516949+0800 OC基础[87234:11885173] 当前线程:<NSThread: 0x60000046c500>{number = 4, name = 我是线程2售票窗口} 剩余票数9
2018-04-12 10:00:28.722266+0800 OC基础[87234:11885174] 当前线程:<NSThread: 0x60000046c0c0>{number = 5, name = 我是线程3售票窗口} 剩余票数8
2018-04-12 10:00:29.923215+0800 OC基础[87234:11885172] 当前线程:<NSThread: 0x60000046c4c0>{number = 3, name = 我是线程1售票窗口} 剩余票数7
2018-04-12 10:00:31.126571+0800 OC基础[87234:11885173] 当前线程:<NSThread: 0x60000046c500>{number = 4, name = 我是线程2售票窗口} 剩余票数6
2018-04-12 10:00:32.329425+0800 OC基础[87234:11885174] 当前线程:<NSThread: 0x60000046c0c0>{number = 5, name = 我是线程3售票窗口} 剩余票数5
2018-04-12 10:00:33.532408+0800 OC基础[87234:11885172] 当前线程:<NSThread: 0x60000046c4c0>{number = 3, name = 我是线程1售票窗口} 剩余票数4
2018-04-12 10:00:34.737175+0800 OC基础[87234:11885173] 当前线程:<NSThread: 0x60000046c500>{number = 4, name = 我是线程2售票窗口} 剩余票数3
2018-04-12 10:00:35.941494+0800 OC基础[87234:11885174] 当前线程:<NSThread: 0x60000046c0c0>{number = 5, name = 我是线程3售票窗口} 剩余票数2
2018-04-12 10:00:37.145875+0800 OC基础[87234:11885172] 当前线程:<NSThread: 0x60000046c4c0>{number = 3, name = 我是线程1售票窗口} 剩余票数1
2018-04-12 10:00:38.353758+0800 OC基础[87234:11885173] 当前线程:<NSThread: 0x60000046c500>{number = 4, name = 我是线程2售票窗口} 剩余票数0
2018-04-12 10:00:39.561668+0800 OC基础[87234:11885174] 销售完毕
2018-04-12 10:00:39.561895+0800 OC基础[87234:11885172] 销售完毕
2018-04-12 10:00:39.562236+0800 OC基础[87234:11885173] 销售完毕
完美解决。