一.什么是多线程
把不同的任务放到不通的线程当中去,解决界面卡死问题
二.NSThread
2.1 三种创建线程方式
//第一种创建线程的方式
[self performSelectorInBackground:@selector(thread1) withObject:nil];
//创建线程的第二种方式
[NSThread detachNewThreadSelector:@selector(thread2:) toTarget:self withObject:@(100)];
//创建线程的第三种方式
NSThread *thread = [[NSThread alloc]initWithTarget:self selector:@selector(thread3) object:nil];
[thread setName:@"thread3"];
[thread start];
2.2 监听线程结束
[[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(myThreadFinish:) name:NSThreadWillExitNotification object:nil];
- (void)myThreadFinish:(NSNotification *)notification
{
NSThread *thread = [notification object];
if ([thread.name isEqualToString:@"thread3"])
{
NSLog(@"thread3 finish!");
}
NSLog(@"thread ===%@",thread);
}
2.3 线程间通讯
- (void)thread4
{
for (int i = 0; i<10; i++)
{
NSLog(@"thread4 i===%d",i);
[NSThread sleepForTimeInterval:1.0];
if (i == 8)
{
//给_thread5发cancel消息.仅仅只是发消息,处不处理,由_thread5自己决定
[_thread5 cancel];
}
}
}
- (void)thread5
{
int i = 0;
while (1)
{
NSLog(@"thread5===%d",i);
[NSThread sleepForTimeInterval:1.0];
i++;
//如果thread5 接收到了cancel消息,就退出
if ([[NSThread currentThread]isCancelled])
{
NSLog(@"thread5 exit");
//执行线程退出
[NSThread exit];
}
}
}
2.4 线程锁
_sumLock = [[NSLock alloc]init];
_sum = 0;
[_sumLock lock];
_sum ++;
[NSThread sleepForTimeInterval:1.0];
[_sumLock unlock];
2.5 子线程刷新UI
_progress = [[UIProgressView alloc]initWithFrame:CGRectMake(100, 100, 200, 30)];
[self.view addSubview:_progress];
[self performSelectorInBackground:@selector(myThread) withObject:nil];
- (void)myThread
{
for (int i=1; i<11; i++)
{
[self performSelectorOnMainThread:@selector(myMain:) withObject:@(i) waitUntilDone:YES];
[NSThread sleepForTimeInterval:1];
}
}
- (void)myMain:(NSNumber *)number
{
NSLog(@"number==%@",number);
[_progress setProgress:number.floatValue*0.1 animated:YES];
}
三.NSOperationQueue
3.1 NSInvocationOperation
NSInvocationOperation *operation1= [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(myOperation1) object:nil];
3.2 NSBlockOperation
NSBlockOperation *operation2 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@" i am operation2");
[NSThread sleepForTimeInterval:5];
}];
3.3 自定义的operation
NSArray *urlArrays = [NSArray arrayWithObjects:@"http://s8.mogucdn.com/pic/141109/49ssv_ieydmolegjsdqyzwmqytambqgiyde_173x80.jpg", @"http://s8.mogucdn.com/pic/141118/7jax4_ieydkntggvrwknzzmqytambqmmyde_173x80.jpg", @"http://s7.mogucdn.com/pic/141111/anxuan_ieygkyjzgnsdanrxmqytambqmmyde_173x80.jpg", nil];
for (int i = 0; i<3; i++)
{
UIImageView *imgView = [[UIImageView alloc]initWithFrame:CGRectMake(10, 30+110*i, 100, 100)];
imgView.tag = 100+i;
imgView.backgroundColor = [UIColor blackColor];
[self.view addSubview:imgView];
}
//创建任务池
NSOperationQueue *queue = [[NSOperationQueue alloc]init];
queue.maxConcurrentOperationCount = 1;
for (int i =0; i<urlArrays.count; i++)
{
MyOperation *operation = [[MyOperation alloc]initWithURL:[urlArrays objectAtIndex:i] completionCallBack:^(MyOperation *operation, NSData *data) {
//取到和operation对应的UIImageView
UIImageView *imgView =(UIImageView *) [self.view viewWithTag:operation.tag];
UIImage *image = [UIImage imageWithData:data];
imgView.image = image;
}];
operation.tag = 100+i;
[queue addOperation:operation];
}
@class MyOperation;
//回调的blocks
typedef void (^completionCallBack)(MyOperation *operation,NSData *data);
@interface MyOperation : NSOperation<NSURLConnectionDataDelegate>
//tag的作用是为了和imgview对应
@property (nonatomic,assign)int tag;
- (id)initWithURL:(NSString *)URL completionCallBack:(completionCallBack)callback;
- (void)main
{
NSURL *url = [NSURL URLWithString:_url];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
[NSURLConnection connectionWithRequest:request delegate:self];
NSLog(@"distantFutureTime===%@",[[NSDate distantFuture]description]);
if (!_isfinishDownload) {
// NSRunLoop 是一个循环事件,每一个viewcontroller都有一个runloop
// NSRunLoop 有任务就坐任务,没任务就等待
// [NSDate distantFuture] 永远不会到达的时间
NSLog(@"currentRunLoop");
[[NSRunLoop currentRunLoop]runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
}
}
3.4只有将operation加入到线程池,方可运行
NSOperationQueue *queue = [[NSOperationQueue alloc]init];
queue.maxConcurrentOperationCount =2;
//将operation添加进线程池,operation添加进线程池,立刻开始运行
[queue addOperation:operation1];
[queue addOperation:operation2];
[queue addOperation:operation3];
四.GCD
4.1GCD种类
/第一种,取得主线程:ios自带
_mainQueue = dispatch_get_main_queue();
//第二种,取得全局的一个线程:ios自带
_globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
//第三种GCD多线程,用户自己创建的线程
//第一个参数:myQueue 是一个字符串,作标识
//第二个参数:这个GCD队列是串行还是并行
//DISPATCH_QUEUE_SERIAL 串行
//DISPATCH_QUEUE_CONCURRENT 并行
//串行 就是队列里面,挨个执行.先来的先执行
//并行 一起上
_userQueue = dispatch_queue_create("myQueue", DISPATCH_QUEUE_SERIAL);
4.2 GCD调度方式
//同步方式进行调用==串行
dispatch_sync(<#dispatch_queue_t queue#>, <#^(void)block#>)
//异步方式进行调用==并行
dispatch_async(<#dispatch_queue_t queue#>, <#^(void)block#>)
// _mainQueue 不管你用何种方式去调度它,它都是串行
//主线程不要使用同步的方式进行调度,会阻塞UI
dispatch_async(_mainQueue, ^{
NSLog(@"1");
});
dispatch_async(_mainQueue, ^{
NSLog(@"2");
});
//_globalQueue 全局队列
//如果使用dispatch_sync 同步方式去调度,就是串行
//如果使用dispatch_async 异步方式进行调度,就是并行
dispatch_sync(_globalQueue, ^{
NSLog(@"A");
});
dispatch_sync(_globalQueue, ^{
NSLog(@"B");
});
//用户自己创建的队列
//用户自己创建的队列,只要是用同步方式进行调度(dispatch_sync),则一定是串行
//只有异步调用(dispatch_async)+ DISPATCH_QUEUE_CONCURRENT(并行)才是并行调用
dispatch_async(_userQueue, ^{
NSLog(@"a");
});
dispatch_async(_userQueue, ^{
NSLog(@"b");
});
4.3 GCD刷UI
_progress = [[UIProgressView alloc]initWithFrame:CGRectMake(50, 100, 200, 30)];
_progress.progress = 0;
[self.view addSubview:_progress];
dispatch_async(_globalQueue, ^{
for ( int i = 1; i<11; i++)
{
float value = i*0.1;
[NSThread sleepForTimeInterval:1.0];
dispatch_async(_mainQueue, ^{
[_progress setProgress:value animated:YES];
});
}
});
// GCD单例写法
+ (id)shareInstance
{
static dispatch_once_t onceToken;
static ViewController * ctl = nil;
dispatch_once(&onceToken, ^{
// 保证下面的代码只会执行一次
ctl = [[ViewController alloc] init];
});
return ctl;
}
把不同的任务放到不通的线程当中去,解决界面卡死问题
二.NSThread
2.1 三种创建线程方式
//第一种创建线程的方式
[self performSelectorInBackground:@selector(thread1) withObject:nil];
//创建线程的第二种方式
[NSThread detachNewThreadSelector:@selector(thread2:) toTarget:self withObject:@(100)];
//创建线程的第三种方式
NSThread *thread = [[NSThread alloc]initWithTarget:self selector:@selector(thread3) object:nil];
[thread setName:@"thread3"];
[thread start];
2.2 监听线程结束
[[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(myThreadFinish:) name:NSThreadWillExitNotification object:nil];
- (void)myThreadFinish:(NSNotification *)notification
{
NSThread *thread = [notification object];
if ([thread.name isEqualToString:@"thread3"])
{
NSLog(@"thread3 finish!");
}
NSLog(@"thread ===%@",thread);
}
2.3 线程间通讯
- (void)thread4
{
for (int i = 0; i<10; i++)
{
NSLog(@"thread4 i===%d",i);
[NSThread sleepForTimeInterval:1.0];
if (i == 8)
{
//给_thread5发cancel消息.仅仅只是发消息,处不处理,由_thread5自己决定
[_thread5 cancel];
}
}
}
- (void)thread5
{
int i = 0;
while (1)
{
NSLog(@"thread5===%d",i);
[NSThread sleepForTimeInterval:1.0];
i++;
//如果thread5 接收到了cancel消息,就退出
if ([[NSThread currentThread]isCancelled])
{
NSLog(@"thread5 exit");
//执行线程退出
[NSThread exit];
}
}
}
2.4 线程锁
_sumLock = [[NSLock alloc]init];
_sum = 0;
[_sumLock lock];
_sum ++;
[NSThread sleepForTimeInterval:1.0];
[_sumLock unlock];
2.5 子线程刷新UI
_progress = [[UIProgressView alloc]initWithFrame:CGRectMake(100, 100, 200, 30)];
[self.view addSubview:_progress];
[self performSelectorInBackground:@selector(myThread) withObject:nil];
- (void)myThread
{
for (int i=1; i<11; i++)
{
[self performSelectorOnMainThread:@selector(myMain:) withObject:@(i) waitUntilDone:YES];
[NSThread sleepForTimeInterval:1];
}
}
- (void)myMain:(NSNumber *)number
{
NSLog(@"number==%@",number);
[_progress setProgress:number.floatValue*0.1 animated:YES];
}
三.NSOperationQueue
3.1 NSInvocationOperation
NSInvocationOperation *operation1= [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(myOperation1) object:nil];
3.2 NSBlockOperation
NSBlockOperation *operation2 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@" i am operation2");
[NSThread sleepForTimeInterval:5];
}];
3.3 自定义的operation
NSArray *urlArrays = [NSArray arrayWithObjects:@"http://s8.mogucdn.com/pic/141109/49ssv_ieydmolegjsdqyzwmqytambqgiyde_173x80.jpg", @"http://s8.mogucdn.com/pic/141118/7jax4_ieydkntggvrwknzzmqytambqmmyde_173x80.jpg", @"http://s7.mogucdn.com/pic/141111/anxuan_ieygkyjzgnsdanrxmqytambqmmyde_173x80.jpg", nil];
for (int i = 0; i<3; i++)
{
UIImageView *imgView = [[UIImageView alloc]initWithFrame:CGRectMake(10, 30+110*i, 100, 100)];
imgView.tag = 100+i;
imgView.backgroundColor = [UIColor blackColor];
[self.view addSubview:imgView];
}
//创建任务池
NSOperationQueue *queue = [[NSOperationQueue alloc]init];
queue.maxConcurrentOperationCount = 1;
for (int i =0; i<urlArrays.count; i++)
{
MyOperation *operation = [[MyOperation alloc]initWithURL:[urlArrays objectAtIndex:i] completionCallBack:^(MyOperation *operation, NSData *data) {
//取到和operation对应的UIImageView
UIImageView *imgView =(UIImageView *) [self.view viewWithTag:operation.tag];
UIImage *image = [UIImage imageWithData:data];
imgView.image = image;
}];
operation.tag = 100+i;
[queue addOperation:operation];
}
@class MyOperation;
//回调的blocks
typedef void (^completionCallBack)(MyOperation *operation,NSData *data);
@interface MyOperation : NSOperation<NSURLConnectionDataDelegate>
//tag的作用是为了和imgview对应
@property (nonatomic,assign)int tag;
- (id)initWithURL:(NSString *)URL completionCallBack:(completionCallBack)callback;
- (void)main
{
NSURL *url = [NSURL URLWithString:_url];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
[NSURLConnection connectionWithRequest:request delegate:self];
NSLog(@"distantFutureTime===%@",[[NSDate distantFuture]description]);
if (!_isfinishDownload) {
// NSRunLoop 是一个循环事件,每一个viewcontroller都有一个runloop
// NSRunLoop 有任务就坐任务,没任务就等待
// [NSDate distantFuture] 永远不会到达的时间
NSLog(@"currentRunLoop");
[[NSRunLoop currentRunLoop]runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
}
}
3.4只有将operation加入到线程池,方可运行
NSOperationQueue *queue = [[NSOperationQueue alloc]init];
queue.maxConcurrentOperationCount =2;
//将operation添加进线程池,operation添加进线程池,立刻开始运行
[queue addOperation:operation1];
[queue addOperation:operation2];
[queue addOperation:operation3];
四.GCD
4.1GCD种类
/第一种,取得主线程:ios自带
_mainQueue = dispatch_get_main_queue();
//第二种,取得全局的一个线程:ios自带
_globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
//第三种GCD多线程,用户自己创建的线程
//第一个参数:myQueue 是一个字符串,作标识
//第二个参数:这个GCD队列是串行还是并行
//DISPATCH_QUEUE_SERIAL 串行
//DISPATCH_QUEUE_CONCURRENT 并行
//串行 就是队列里面,挨个执行.先来的先执行
//并行 一起上
_userQueue = dispatch_queue_create("myQueue", DISPATCH_QUEUE_SERIAL);
4.2 GCD调度方式
//同步方式进行调用==串行
dispatch_sync(<#dispatch_queue_t queue#>, <#^(void)block#>)
//异步方式进行调用==并行
dispatch_async(<#dispatch_queue_t queue#>, <#^(void)block#>)
// _mainQueue 不管你用何种方式去调度它,它都是串行
//主线程不要使用同步的方式进行调度,会阻塞UI
dispatch_async(_mainQueue, ^{
NSLog(@"1");
});
dispatch_async(_mainQueue, ^{
NSLog(@"2");
});
//_globalQueue 全局队列
//如果使用dispatch_sync 同步方式去调度,就是串行
//如果使用dispatch_async 异步方式进行调度,就是并行
dispatch_sync(_globalQueue, ^{
NSLog(@"A");
});
dispatch_sync(_globalQueue, ^{
NSLog(@"B");
});
//用户自己创建的队列
//用户自己创建的队列,只要是用同步方式进行调度(dispatch_sync),则一定是串行
//只有异步调用(dispatch_async)+ DISPATCH_QUEUE_CONCURRENT(并行)才是并行调用
dispatch_async(_userQueue, ^{
NSLog(@"a");
});
dispatch_async(_userQueue, ^{
NSLog(@"b");
});
4.3 GCD刷UI
_progress = [[UIProgressView alloc]initWithFrame:CGRectMake(50, 100, 200, 30)];
_progress.progress = 0;
[self.view addSubview:_progress];
dispatch_async(_globalQueue, ^{
for ( int i = 1; i<11; i++)
{
float value = i*0.1;
[NSThread sleepForTimeInterval:1.0];
dispatch_async(_mainQueue, ^{
[_progress setProgress:value animated:YES];
});
}
});
// GCD单例写法
+ (id)shareInstance
{
static dispatch_once_t onceToken;
static ViewController * ctl = nil;
dispatch_once(&onceToken, ^{
// 保证下面的代码只会执行一次
ctl = [[ViewController alloc] init];
});
return ctl;
}