iOS开发多线程网络———NSThread
NSThread概念
NSThree是官方推荐的线程处理方式,它在处理机制上,需要开发者负责手动管理Thread的生命周期,包括子线程与主线程之间的同步等。线程共享同一应用程序的部分内存空间,它们拥有对数据相同的访问权限。你得协调多个线程 对同一数据的访问,一般做法是在访问之前加锁,在 iOS 中我们可以使用多种形式的 thread。 比其他两个轻量级 需要自己管理线程的生命周期,线程同步。 线程同步对数据的加锁会有一定的系统开销
a.开启后台执行任务的方法
- (void)performSelectorInBackground:(SEL)aSelector withObject:(id)arg
b.在后台线程中通知主线程执行任务的方法
- (void)performSelectorOnMainThread:(SEL)aSelector withObject:(id)arg waitUntilDone:(BOOL)wait
c.获取线程信息
[NSThreadcurrentThread]
d.线程休眠
[NSThread sleepForTimeInterval:2.0f];
特点:
使用简单,量级轻
不能控制线程的数量以及执行顺序
1 #import "LDViewController.h"
3 需求分析
4
5 1. UIImageView显示图片
6 2. UIImage模拟从网络上下载
7 3. NSString记录图片路径
8
9 小结
10
11 方法,看起来很简单,
12
13 1> 不能够自动回收线程,如果并发数量多,会建立大量的子线程!
14 2> 使用NSThread的线程,不会自动添加autoreleasepool
15
16 意味着,如果在后台线程方法中,
17
18 @autoreleasepool {} 自动释放池
19
20 主线程中是有自动释放池的,使用GCD和NSOperation也会自动添加自动释放池
21
22 NSThread和NSObject不会,如果在后台线程中创建了autorelease的对象,需要使用自动释放池,否则会出现内存泄漏!
23
24 工作原理:
25
26 1. 当自动释放池被销毁或者“耗尽”时,对池中的所有对象发送release消息,清空自动释放池
27 2. 所有autorelease的对象,在出了作用域之后,会自动添加到【最近一次创建的自动释放池中】自动释放池中
28
29 在ARC中,编译器在编译过程中,会自动根据代码结构,添加retain和release。
30 */
31 @interface LDViewController ()
32
33 @property (nonatomic, strong) UIImageView *imageView;
34 @property (nonatomic, strong) UIImage *image;
35 @property (nonatomic, strong) NSString *imagePath;
36
37 @end
38
39 @implementation LDViewController
40
41 // 0. 模拟使用图像路径加载图片
42 - (void)setImagePath:(NSString *)imagePath
43 {
44 @autoreleasepool {
45 NSLog(@"%@", [NSThread currentThread]);
46
47 // 1> 模拟下载,延时
48 [NSThread sleepForTimeInterval:1.0];
49
50 // 2> 设置图像,苹果底层允许使用performSelectorInBackground方法
51 // 在后台线程更新UI,强烈不建议大家这么做!
52 // YES会阻塞住线程,直到调用方法完成
53 // NO不会阻塞线程,会继续执行
54 [self performSelectorOnMainThread:@selector(setImage:) withObject:[UIImage imageNamed:imagePath] waitUntilDone:NO];
55 }
56 }
57
58 // 1. 图像
59 - (void)setImage:(UIImage *)image
60 {
61
62 self.imageView.image = image;
63
64 // [NSThread sleepForTimeInterval:1.0];
65 // 根据图片自动调整大小
66 [self.imageView sizeToFit];
67 }
68
69 // 2. 创建imageView
70 - (UIImageView *)imageView
71 {
72 if (!_imageView) {
73 _imageView = [[UIImageView alloc] init];
74 }
75
76 return _imageView;
77 }
78
79 - (void)viewDidLoad
80 {
81 [super viewDidLoad];
82
83 [self.view addSubview:self.imageView];
84
85 // 在后台线程执行这段代码即可
86 for (int i = 0; i < 50; ++i) {
87 [self performSelectorInBackground:@selector(setImagePath:) withObject:@"头像1.png"];
88 }
89 // [self setImagePath: @"头像1.png"];
90 }
91
92 - (void)demo
93 {
94 // 提问:代码存在什么问题?如果循环次数非常大,会出现什么问题?应该如何修改?
95
96 // 解决办法1:如果i比较大,可以用@autoreleasepool(在for循环外)
97 // 解决方法2:如果i玩命大,一次循环都会造成自动释放池被填满可以用@autoreleasepool(在for循环内如下:)
98 for (int i = 0; i < 10000000; ++i) {
99 @autoreleasepool {
100 // *
101 NSString *str = @"Hello World!";
102 // new *
103 str = [str uppercaseString];
104 // new *
105 str = [NSString stringWithFormat:@"%@ %d", str, i];
106
107 NSLog(@"%@", str);
108 }
109 }
110 }
111
112 @end
NSObject的多线程方法注意事项:
a.NSObject的多线程方法使用的是NSThread得多线程技术,而NSThread的多线程技术不会自动使用@autoreleasepool
b.在使用NSObject或NSThread的多线程技术时,如果涉及到对象分配,需要手动添加@autoreleasepool
@autoreleasepool 简单介绍
1.iOS开发中的内存管理
a.在iOS开发中,并没有JAVA或C#中的垃圾回收机制
b.使用ARC开发,只是在编译时,编译器会根据代码结构自动添加了retain、release和autorelease