无论使用哪种多线程技术都可以使用
[NSThread
currentThread]跟踪查看当前执行所在的线程情况。
num =
1表示在主线程上执行的任务
http://www.cnblogs.com/mcj-coding/p/3556419.html
================================================================
1.
NSObject多线程技术
1>
使用performSelectorInBackground可以开启后台线程,执行selector选择器选择的方法
2>
使用performSelectorOnMainThread可以重新回到主线程执行任务,通常用于后台线程更新界面UI时使用
3>
[NSThread sleepForTimeInterval:1.0f];
让当前线程休眠,通常在程序开发中,用于模拟耗时操作,以便跟踪不同的并发执行情况!
但是:在程序发布时,千万不要保留此方法!不要把测试中的代码交给客户,否则会造成不好的用户体验。
提示:使用performSelectorInBackground也可以直接修改UI,但是强烈不建议使用。
注意:在使用NSThread或者NSObject的线程方法时,一定要使用自动释放池,否则容易出现内存泄露。
================================================================
2.
NSThread的多线程技术,仅了解即可,使用极少!
1>
类方法直接开启后台线程,并执行选择器方法
detachNewThreadSelector
2>
成员方法,在实例化线程对象之后,需要使用start执行选择器方法
initWithTarget
对于NSThread的简单使用,可以用NSObject的performSelectorInBackground替代
同时,在NSThread调用的方法中,同样要使用autoreleasepool进行内存管理,否则容易出现内存泄露。
================================================================
3.
NSOperation,面向对象的多线程技术
1> 使用步骤:
1)
实例化操作
a)
NSInvocationOperation
b)
NSBlockOperation
2)
将操作添加到队列NSOperationQueue即可启动多线程执行
2>
更新UI使用主线程队列
[NSOpeationQueue mainQueue] addOperation
^{};
3>
操作队列的setMaxConcurrentOperationCount
可以设置同时并发的线程数量!
提示:此功能仅有NSOperation有!
4>
使用addDependency可以设置任务的执行先后顺序,同时可以跨操作队列指定依赖关系
提示:在指定依赖关系时,注意不要循环依赖,否则不工作。
================================================================
4.
GCD,C语言
GCD就是为了在“多核”上使用多线程技术
1>
要使用GCD,所有的方法都是dispatch开头的
2> 名词解释
global
全局
queue 队列
async
异步
sync 同步
3>
要执行异步的任务,就在全局队列中执行即可
dispatch_async
异步执行控制不住先后顺序
4> 关于GCD的队列
全局队列
dispatch_get_global_queue
参数:优先级
DISPATCH_QUEUE_PRIORITY_DEFAULT
始终是 0
串行队列
dispatch_queue_create("myQueue",
DISPATCH_QUEUE_SERIAL);
是创建得到的,不能直接获取
主队列
dispatch_get_main_queue
5>
异步和同步与方法名无关,与运行所在的队列有关!
提示:要熟悉队列于同步、异步的运行节奏,一定需要自己编写代码测试!
同步主要用来控制方法的被调用的顺序
实例代码
- (void)viewDidLoad
{
[super
viewDidLoad];
NSLog(@"%@",
[NSThread currentThread]);
//
实例化操作队列
_queue = [[NSOperationQueue alloc]
init];
}
#pragma mark - 操作
// 耗时操作演示
-
(void)bigDemo
{
// 自动释放池
//
负责其他线程上的内存管理,在使用NSThread或者NSObject的线程方法时,一定要使用自动释放池
//
否则容易出现内存泄露。
@autoreleasepool
{
// //
模拟网络下载延时
// for
(NSInteger i = 0; i < 1000; i++)
{
// NSString *str = [NSString
stringWithFormat:@"%d", i];
//
// //
提示:NSLog是非常耗时的操作!
// NSLog(@"大任务-> %@",
str);
//
}
NSLog(@"%@", [NSThread
currentThread]);
//
模拟网络下载延时,睡眠1秒,通常是在开发中测试使用。
[NSThread sleepForTimeInterval:1.0f];
//
强烈不建议直接在后台线程更新界面UI!
//
模拟获取到下载的图像
UIImage *image =
[UIImage imageNamed:@"头像1"];
//
在主线程更新图像
//
使用self调用updateImage方法在主线程更新图像
// [self performSelectorOnMainThread:@selector(updateImage:)
withObject:image waitUntilDone:YES];
//
使用imageView的setImage方法在主线程更新图像
[_imageView performSelectorOnMainThread:@selector(setImage:) withObject:image
waitUntilDone:YES];
//
....
}
}
#pragma mark -
更新图像,模拟从网络上下载完图片后,更新界面的操作
- (void)updateImage:(UIImage
*)image
{
NSLog(@"更新图像-> %@", [NSThread
currentThread]);
_imageView.image =
image;
}
#pragma mark - Actions
-
(IBAction)bigTask
{
//
本方法中的所有代码都是在主线程中执行的
// NSObject多线程技术
NSLog(@"执行前->%@", [NSThread currentThread]);
//
performSelectorInBackground是将bigDemo的任务放在后台线程中执行
[self
performSelectorInBackground:@selector(bigDemo) withObject:nil];
NSLog(@"执行后->%@", [NSThread
currentThread]);
// [self bigDemo];
NSLog(@"执行完毕");
}
-
(IBAction)smallTask
{
NSString *str =
nil;
for (NSInteger i = 0; i <
50000; i++) {
str = [NSString
stringWithFormat:@"%d", i];
}
NSLog(@"小任务-> %@", str);
}
#pragma
mark NSThread演练
- (IBAction)threadDemo
{
//
新建一个线程,调用@selector方法
// [NSThread
detachNewThreadSelector:@selector(bigDemo) toTarget:self
withObject:nil];
//
成员方法
NSThread *thread = [[NSThread alloc]
initWithTarget:self selector:@selector(bigDemo) object:nil];
// 启动start线程
[thread
start];
}
#pragma mark - NSOperation演练
-
(void)opAction
{
NSLog(@"%@", [NSThread
currentThread]);
//
模拟延时
[NSThread sleepForTimeInterval:1.0f];
// 模拟获取到图像
UIImage *image =
[UIImage imageNamed:@"头像1"];
//
设置图像,在主线程队列中设置
[[NSOperationQueue mainQueue]
addOperationWithBlock:^{
_imageView.image = image;
}];
}
#pragma mark
invocation
- (IBAction)operationDemo1
{
NSInvocationOperation *op1 = [[NSInvocationOperation alloc] initWithTarget:self
selector:@selector(opAction) object:nil];
// 如果使用start,会在当前线程启动操作
//
[op1 start];
// 1.
一旦将操作添加到操作队列,操作就会启动
[_queue
addOperation:op1];
}
#pragma mark blockOperation
-
(IBAction)operationDemo2
{
//
用block的最大好处,可以将一组相关的操作,顺序写在一起,便于调试以及代码编写
[_queue
addOperationWithBlock:^{
NSLog(@"%@", [NSThread currentThread]);
//
模拟延时
[NSThread
sleepForTimeInterval:1.0f];
//
模拟获取到图像
UIImage *image = [UIImage
imageNamed:@"头像1"];
//
设置图像,在主线程队列中设置
[[NSOperationQueue
mainQueue]
addOperationWithBlock:^{
_imageView.image = image;
}];
}];
}
#pragma mark 模仿下载网络图像
-
(IBAction)operationDemo3:(id)sender
{
// 1.
下载
NSBlockOperation *op1 = [NSBlockOperation
blockOperationWithBlock:^{
NSLog(@"下载 %@" , [NSThread currentThread]);
}];
// 2. 滤镜
NSBlockOperation *op2 =
[NSBlockOperation
blockOperationWithBlock:^{
NSLog(@"滤镜 %@" , [NSThread currentThread]);
}];
// 3. 显示
NSBlockOperation *op3 =
[NSBlockOperation
blockOperationWithBlock:^{
NSLog(@"更新UI %@" , [NSThread currentThread]);
}];
//
添加操作之间的依赖关系,所谓“依赖”关系,就是等待前一个任务完成后,后一个任务才能启动
//
依赖关系可以跨线程队列实现
//
提示:在指定依赖关系时,注意不要循环依赖,否则不工作。
[op2
addDependency:op1];
[op3
addDependency:op2];
// [op1
addDependency:op3];
[_queue
addOperation:op1];
[_queue
addOperation:op2];
[[NSOperationQueue mainQueue]
addOperation:op3];
}
#pragma mark 限制线程数量
-
(IBAction)operationDemo4
{
//
控制同时最大并发的线程数量
[_queue
setMaxConcurrentOperationCount:2];
for (NSInteger i = 0; i < 200; i++)
{
NSBlockOperation *op =
[NSBlockOperation
blockOperationWithBlock:^{
NSLog(@"%@", [NSThread
currentThread]);
}];
[_queue
addOperation:op];
}
}
#pragma mark - GCD演练
-
(IBAction)gcdDemo1
{
// 1.
队列
dispatch_queue_t queue =
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
// 2. 将任务异步(并发)执行
dispatch_async(queue, ^{
NSLog(@"a->%@", [NSThread currentThread]);
});
dispatch_async(queue,
^{
NSLog(@"b->%@", [NSThread
currentThread]);
});
dispatch_async(dispatch_get_main_queue(),
^{
NSLog(@"main - > %@",
[NSThread currentThread]);
});
}
#pragma mark
串行队列
- (IBAction)gcdDemo2
{
// 1.
队列,串行队列需要自行创建,不能get
dispatch_queue_t queue =
dispatch_queue_create("myQueue", DISPATCH_QUEUE_SERIAL);
dispatch_sync(queue,
^{
NSLog(@"a->%@", [NSThread
currentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"b->%@", [NSThread currentThread]);
});
}
@end
原文:http://www.cnblogs.com/mcj-coding/p/3556419.html