爱程序网

线程

来源: 阅读:

线程问题我会分成三篇文章来给大家做个详细的讲解

一、线程的概念

1.线程是进程的组成部分,一个进程可以拥有多个线程,一个线程必须有一个父线程;

2.线程拥有自己的堆栈、自己的程序计数器和自己的局部变量,但不再拥有系统资源,它与父线程中的其他线程共享该进程所拥有的全部资源

3.线程是独立运行的,它并不知道进程中是否还有其他线程存在,线程的执行是抢占式的,也就是说当前的运行的线程在任何时候都可能被挂起,以便另外一个线程可以运行。

使用多线程编程的优点

1、进程间不能共享内存,但线程之间共享内存非常容易

2、系统创建进程需要重新为该进程分配资源,但是创建线程则代价小得多,因为它与父线程中的其他线程共享该进程所拥有的全部资源

3、处理异步任务的主要手段,可防止UI界面假死

线程的创建方法:

1)创建线程并执行线程

+ (void)detachNewThreadSelector: toTarget: withObject:

 

2)创建一个线程并返回一个线程对象但是不会执行,需要手动调用start

- (instancetype)initWithTarget: selector: object:

 

 

二、线程的状态

1、当程序创建了一个线程后,该程序就处于新建状态,此时它与其他OC对象一样,仅仅由系统为其分配了内存,并初始化了其成员变量的值,此时的线程对象没有表现任何线程的动态特征,程序也不会执行线程的线程执行体

2、当线程对象调用了start方法之后,该线程处于就绪状态,系统会为其调用方法调用栈和程序计数器,处于这种状态的线程并没有开始运行,他只是表示该线程可以运行了,至于线程何时开始运行,取决于系统的调度;倘若希望调用子线程的start方法之后子线程立即开始执行,可以在程序中加上

[NSThread sleepForTimeInterval:0.001];   //写在哪个线程中代表哪个线程

让当前运行的线程睡眠一毫秒,因为在这一毫秒内CPU不会空闲,他会去执行另一个处于就绪状态的线程,这就可以让子线程立即获得执行

 

三、终止子线程

线程会以以下三种方式之一结束,结束之后就处于死亡状态

1、线程执行体方法执行完成,线程正常结束

2、线程执行过程中出现了错误

3、直接调用NSThread类的exit方法来终止当前正在执行的线程

对象方法

isExecuting、isFinishing判断线程当前是否处于执行状态或者执行完成状态

如果希望在主线程中终止子线程,NSThread并没有提供方法来终止某个子线程,为了在子线程中终止子线程,可以向子线程发送一个信号(比如调用子线程的cancel方法),然后在子线程的线程执行体重进行判断,如果子线程收到过终止信号,程序应该调用NSThread类的exit方法来终止当前正在执行的循环

 

四、线程睡眠

如果需要让当前正在执行的线程暂停一段时间,并进入阻塞状态,则可以通过调用NSThread类的sleepXXX类方法来完成

+ (void)sleepForTimeInterval:(NSTimeInterval)ti;    //每隔多久执行一次 

+ (void)sleepUntilDate:(NSDate *)date;     //指定睡眠指导某个时间执行

 

 1 - (void)viewDidLoad {
 2     [super viewDidLoad];
 3     // NSThread 两种创建线程的方式
 4 #if 1
 5     //1.该方法创建的线程需要手动调用启动,才会去执行线程指定的方法
 6     // 线程需要一个函数作为线程的入口函数,这个函数称为线程的入口函数
 7     //  线程主要用来做并发操作,例如执行耗时的代码
 8    NSThread *tread = [[NSThread alloc] initWithTarget:self selector:@selector(doSomething) object:nil];
 9     for (int i = 0; i < 100; i++) {
10         if (i == 20) {  
11             //需要手动执行开始,才会调用doSomething的方法
12             [tread start];
13             [NSThread sleepForTimeInterval:0.001];
14         }
15         NSLog(@"%d",i);
16     }
17     //给线程取别名
18     //tread.name = @"something";
19 
20 #elif 0
21     //2.该方式创建的线程会自动执行线程的入口函数
22     [NSThread detachNewThreadSelector:@selector(doSomething) toTarget:self withObject:nil];
23   #endif
24 }
25 -(void)doSomething
26 {
27     // 耗时代码
28     
29     // 获取当前线程
30     //NSLog(@"%@",[NSThread currentThread]);
31     int index = 10;
32     
33     while (index--) {
34         
35         if (index == 5) {
36             //1⃣️cancel 取消线程,并不是真正意义上的取消线程,是给线程打上取消的标志,等待取消
37             [[NSThread currentThread] cancel];
38         }
39         
40         //2⃣️.判断线程是否有取消的标志
41         if ([[NSThread currentThread] isCancelled]) {
42             //3⃣️.退出线程,线程销毁,系统会自动回收资源
43             //[NSThread exit];
44             //注意return与退出线程的区别
45             //return;
46         }
47         
48         NSLog(@"%d",index);
49         //两种睡眠方式
50         //1.睡眠
51         //[NSThread sleepForTimeInterval:1];
52         //2.指定睡眠知道某个时间执行
53         //dateByAddingTimeInterval 追加的时间
54 //        NSDate *curDate = [[NSDate date] dateByAddingTimeInterval:1];
55 //        [NSThread sleepUntilDate:curDate];
56     }
57 }

 

【注意】iOS规定只能在UI线程(即主线程)中修改UI控件的属性,因为如果程序允许任意子线程访问、修改UI控件的属性,这就需要对多个新线程的并发访问进行同步控制;否则,多个线程将会破坏UI控件内部状态的完整性

实例:下载网络图片(如果程序在UI线程中访问网络数据,由于网络速度的不确定性,当网络传输速度比较慢时,UI线程就会被阻塞,从而导致应用失去响应,因此程序将通过网络下载图片的操作放在多线程中完成)

 1 #import "ViewController.h"
 2 
 3 @interface ViewController ()
 4 @property (weak, nonatomic) IBOutlet UIImageView *imageV;
 5 
 6 @end
 7 
 8 @implementation ViewController
 9 
10 - (void)viewDidLoad {
11     [super viewDidLoad];
12     
13 }
14 - (IBAction)BtnAction:(id)sender {
15     //图片地址
16     NSString *url = @"http://image.baidu.com/search/down?tn=download&ipn=dwnl&word=download&ie=utf8&fr=result&url=http%3A%2F%2Fh.hiphotos.baidu.com%2Fzhidao%2Fwh%253D450%252C600%2Fsign%3D3dc4538262d0f703e6e79dd83dca7d0b%2F7a899e510fb30f24f570e996c895d143ac4b03b8.jpg&thumburl=http%3A%2F%2Fimg4.imgtn.bdimg.com%2Fit%2Fu%3D2019970444%2C20888940%26fm%3D21%26gp%3D0.jpg";
17     //创建线程
18     NSThread *downloadImage = [[NSThread alloc] initWithTarget:self selector:@selector(downLoadImage:) object:url];
19     //启动线程
20     [downloadImage start];
21    
22     
23 }
24 -(void)downLoadImage:(NSString *)url
25 {
26     NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:url]];
27     UIImage *image = [UIImage imageWithData:data];
28     //返回主线程刷新UI
29     
30     [self performSelectorOnMainThread:@selector(reloadUI:) withObject:image waitUntilDone:NO];
31 }
32 -(void)reloadUI:(UIImage *)image
33 {
34     _imageV.image = image;
35 }
36 @end

 

 

 

关于爱程序网 - 联系我们 - 广告服务 - 友情链接 - 网站地图 - 版权声明 - 人才招聘 - 帮助