标签:
/ / 是否是多线程
[NSThread isMultiThreaded]
|
//是否是主线程
[NSThread isMainThread]
|
//是否是当前线程
[NSThread currentThread]
|
//1.使用NSThread类方法?detach方法,隐式创建 addAction12就是该线程的入口方法
//注意: 每个线程都有main函数,这里相当于在main函数中self调用了addAction12方法
//这种方式的缺点是非常的不灵活,没办法操作thread,开启时间点也没办法控制
[NSThread detachNewThreadSelector:@selector(addAction12) toTarget:self withObject:nil];
|
//2.使用NSObject的线程扩展perform方法
//隐式方法 与上一个方法使用类似 // [self performSelectorInBackground:@selector(addAction12) withObject:nil];
|
//3.创建一个NSThread对象,然后调用start方法执行:
//显式创建 NSThread* thread = [[NSThread alloc]initWithTarget:self selector:@selector(addAction3) object:nil]; thread.name = @"thread_name"; //配置线程栈空间
//在线程开始之前 设置栈空间才有效,不能使用创建线程的第一和第二种方法
thread.stackSize = 100; //配置线程的本地存储
//线程的全局数据 是readOnly
[thread.threadDictionary setObject:@"value1" forKey:@"key1"]; //错误写法,这是set方法,readOnly不能用 // thread.threadDictionary = [[NSMutableDictionary alloc]init]; //线程的优先级
//范围是0-1,最高是1,iOS8中更新时被qualityOfService代替
/ /根据线程的优先级来决定线程的执行顺序。
thread.threadPriority = 1.0;
thread.qualityOfService = NSQualityOfServiceUserInteractive;//不能再线程start后修改 //开启线程(现在才真正的创建出一个新的线程)
[thread start];
|
//4.创建一个NSThread子类,然后实例化调用start方法
//子类NSThread,重写main方法,,率先进入CNThread的main方法
/ /显示创建
CNThread* cnThread = [[CNThread alloc]init];
[cnThread start];
|
/ /在当前线程中调用
/ /就是viewDidLoad在哪个线程中,直接调用的方法就在哪个线程中
[self addAction12];
[self performSelect…..];
|
- (void)viewDidLoad {
[super viewDidLoad]; NSThread* thread = [[NSThread alloc]initWithTarget:self selector:@selector(threadAction) object:nil]; [thread start]; //如果直接在当前线程中调用循环,就会卡死在这,不会进入程序 // while (true) { // [self action]; // } } - (void)threadAction{ @autoreleasepool { //新线程不会干扰到主线程 [[NSThread currentThread].threadDictionary setObject:@(false) forKey:@"isEixt"]; while (true) { if ([[[NSThread currentThread].threadDictionary valueForKey:@"isEixt"]boolValue]) { return; } //在新线程中调用 [self action]; } } } - (void)action{ count++; if (count == 10000) { [[NSThread currentThread].threadDictionary setObject:@(true) forKey:@"isEixt"]; } NSLog(@"-----,%d",count); }
|
- (void)threadAction{
@autoreleasepool { //新线程不会干扰到主线程 [[NSThread currentThread].threadDictionary setObject:@(false) forKey:@"isEixt"];
NSTimer* timer = [NSTimer timerWithTimeInterval:3 target:self selector:@selector(action) userInfo:nil repeats:YES];
//添加时间源 [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes]; //开启loop方法 [[NSRunLoop currentRunLoop]run];
}
//timer是run起来了,但是怎么终止呢,下面来讲解一下
|
- (void)threadRoutine{
@autoreleasepool {
//每一次的 NSRunloop循环都检查退出条件是否为YES,如果为YES退出循环回收资源,如果为NO,则 进入下一次NSRunloop循环。
BOOL exitNow = NO;
//是否有更多的任务
BOOL moreWorkToDo = YES;
NSRunLoop* runLoop = [NSRunLoop currentRunLoop];
NSMutableDictionary* threadDict = [[NSThread currentThread] threadDictionary]; [threadDict setValue:[NSNumber numberWithBool:exitNow] forKey:@"ThreadShouldExitNow"]; NSTimer* timer = [NSTimer timerWithTimeInterval:3 target:self selector:@selector(action) userInfo:nil repeats:YES];
//添加时间源
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
//终止线程
while (moreWorkToDo && !exitNow)
{
//执?行线程真正的工作方法,如果完成了可以设置moreWorkToDo为False,就是不执行更多的任务了
//打开了runloop,runloop又监听timer,当timer的action执行完以后,该语句才会执行完
[runLoop runUntilDate:[NSDate date]];
exitNow = [[threadDict valueForKey:@"ThreadShouldExitNow"]
boolValue]; } } }
|
- (void)action{
count++;
if (count == 3) {
[[NSThread currentThread].threadDictionary setObject:@(true) forKey:@"ThreadShouldExitNow"]; } NSLog(@"-----,%d",count); }
//执行结果每隔3秒运行一次,执行三次后退出循环
|
//一次Timer事件触发处理后, 这个RunLoop要想有返回值就要用runmode方法
//如果在action中,没有停止RunLoop的操作的话,RunLoop 一直在运行,下面这行代码 永远不会有返回值
BOOL res = [runLoop runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
NSLog(@"%d",res);
|
// 核心代码
//这行代码写在timer的触发事件中
/ /runloop停止
CFRunLoopStop(CFRunLoopGetCurrent());
|
[self doOtherAction];
|
- (void)doOtherAction{
NSLog(@"++++++"); }
//此循环实现了当主线程处于空闲时间时,可以执行其他线程
|
-(void)main
{ @autoreleasepool { NSLog(@"starting thread......."); NSTimer *timer = [NSTimer timerWithTimeInterval:1 target:self selector:@selector(doTimerTask) userInfo:nil repeats:YES]; [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode]; //如果当前线程不被取消,则进入循环 while (!self.isCancelled) { [self doOtherTask]; // 如果在doTimerTask中,没有停止RunLoop的操作的话,RunLoop 一直在运行,下面这行代码 永远不会有返回值 //runloop开始执行 BOOL ret = [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]]; NSLog(@"after runloop counting.........: %d", ret);
}
NSLog(@"finishing thread.........");
} }
|
- (void)doTimerTask
{ NSLog(@"do timer task"); // 添加RunLoop停止代码,使NSRunLoop 的runMode:(NSString *)mode beforeDate:(NSDate *)limitDate方法返回
/ /停止代码必须在runloop运行接口为runMode:下才能用
// 这行代码写在 timer的触发事件中
CFRunLoopStop(CFRunLoopGetCurrent()); }
- (void)doOtherTask { NSLog(@"do other task"); }
|
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(4 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
//4秒过后取消线程 [thread cancel]; });
|
//运? NSRunLoop,运?行模式为默认的NSDefaultRunLoopMode模式,运行起来就永远不会停止
- (void)run;
|
//运?NSRunLoop: 参数为运行时间期限,运?行模式为默认的NSDefaultRunLoopMode模式
-(void)runUntilDate:(NSDate *)limitDate;
|
//运?NSRunLoop: 参数为运?行模式、时间期限,返回值为YES(1)表?示是处理事件后返回的,NO(0)表?示是超时或者停?止运?行导致返回的
- (BOOL)runMode:(NSString *)mode beforeDate:(NSDate *)limitDate;
|
//卖票
- (void)sellTicket{
//获取当前的票数
int current = _ticket;
//若当前票数为0,说明票已经卖完,跳出循环
if (current == 0) {
NSLog(@"ticket:%d,sold:%d",_ticket,_sold); return; } //买票延时 usleep(10000);
//每循环一次,票数久等于当前票数减一
_ticket = current- 1;
NSLog(@"---%@--,%d",[[NSThread currentThread]name],_ticket);
//每循环一次,卖出的票数就加一
_sold++;
//递归调用
[self sellTicket];
}
效果如图
显而易见这个程序是有问题的,每张票在三个窗口都会卖一次,最后卖的票数会多出总票数,要想解决该问题,就要用到数据同步锁
|
//加锁
[_lock lock];
//解锁
[_lock unlock];
|
- (void)viewDidLoad {
[super viewDidLoad]; _lock = [[NSCondition alloc]init];
[self performSelectorInBackground:@selector(cook) withObject:nil];
[self performSelector:@selector(buyStuff) withObject:nil afterDelay:4];
}
|
- (void)cook{
[[NSThread currentThread]setName:@"cook_thread"];
NSLog(@"开始做饭");
NSLog(@"发现没菜,需要去买菜");
[_lock lock];
[_lock wait]; usleep(1000000); NSLog(@"买菜回来,开始做饭"); }
|
- (void)buyStuff{
NSLog(@"买菜进行中。。。。"); //发送信号 [_lock signal];
}
|
标签:
原文地址:http://www.cnblogs.com/gaominmin/p/4822836.html