Object-C学习笔录(四)多线程编程

本文介绍了Objective-C中三种多线程编程方式:NSThread、NSOperation和NSOperationQueue,详细讲解了每种方式的使用方法,包括线程的创建、退出和任务调度,并提供了示例代码。通过NSThread设置线程执行体,通过NSOperationQueue实现并发操作,以及GCD的简要介绍。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

多线程的方式:

有java基础的人都知道java的线程方式有继承Thread类或者实现Runnable接口并覆写run方法;而在Object-C里面创建线程的方式有三种:NSThread创建线程 ;GCD创建线程;NSOperation创建线程

1.1NSThread方式

NSThread创建线程很简单;咱看一段代码就可以明白其原理:

-(void)userNSThread{

    NSThread *thread=[[NSThread alloc] initWithTarget:self selector:@selector(run:) object:@"nnnn"];

    [thread setName:@"subThread"];

    flag=YES;

    [thread start];

}

-(void)run:(NSString *)param{

    while(flag){

        [NSThread sleepForTimeInterval:1.0];

        NSLog(@"------%@------%@-----",[NSThread currentThread],param);   

    }

}

说明:NSThread有两种初始化方式,一种就是上述代码所示的[[NSThread allocinitWithTarget:self selector:@selector(run:) object:@"nnnn"];其中run方法就是线程多执行体,就类似于java线程里面的run方法,只是Object—C的这个run方法的名称是随便取的,还可以传递参数(就是最后的object参数,这里我随便传了一个@"nnnn"),不过只能(至多只能一个参数)传递一个object参数进去,当然对于面向对象的编程,如果要传多个变量进去,我们可以把要传的变量都封装成一个类里面,再将这个类的对象当作参数传进去就OK了。还可以为线程设置名称[thread setName:@"subThread"];。注意这种初始化方式完成之后,还需要调用start方法才会启动线程;这点和java点多线程相似。NSThread的另外一种初始化方式:

[NSThread detachNewThreadSelector:@selector(run:) toTarget:self withObject:@"nnnn"];这种方式创建的线程是匿名的线程,并且他初始化完成就直接启动,而不是等待调用start方法,其他的执行体事run方法,传递参数等都和第一种方式一样;

如何退出一个正在执行对子线程?如果线程的执行体里面有循环,最通用多办法就是设置一个flag信号,把flag加到循环体的判断条件里,到需要停止自线程的时候,只需要把flag值修改一下,线程自动退出。比如:

-(void)run:(NSString *)param{

    while(flag){

        [NSThread sleepForTimeInterval:1.0];

        NSLog(@"------%@------%@-----",[NSThread currentThread],param);   

    }

}

要结束线程,只要把flag的值修改即可;

也可以使用Object-C提供的类方法[NSThread exit];退出,比如在循环体这样写:

-(void)run:(NSString *)param{

    while(true){

        if([NSThread currentThread].isCancelled){

            [NSThread exit];//break;//此处调用break跳出循环体也可以结束线程

        }

        NSLog(@"------%@------",[NSThread currentThread]);

        [NSThread sleepForTimeInterval:1.0];//暂停一秒

    }

}

这样写还需要当想结束线程的时候调用[thread cancel];这样[NSThread currentThread].isCancelled的返回值就变成NO了,

2. NSOperation和NSOperationQueue方式

   首先NSOperation类似于java的Runnable接口;NSOperation有两个子类NSInvocationOperation和NSBlockOperation;类似于Java的Runnable,NSOperation也允许开发者通过继承实现来自定义子类来实现线程,这样开发者只需要重写NSOperation的main方法即可。注意:声明NSOperation 对象也有start方法,但是如果在主线程调用他的start方法;则执行体会被执行,但是是在主线程下执行,而不是新建一个线程;也就是他会在当前调用它start方法的线程里执行;而不是创建新线程。如下代码:

-(void)startOPerationThread{

    NSInvocationOperation *operation=[[NSInvocationOperation alloc] initWithTarget:self selector:@selector(run1:) object:@"nnnn"];

    [operation start];

}

-(void)run1:(NSString *)n{

    NSLog(@"------%@------%@",[NSThread currentThread],n);

}

我们用NSLog打印当前所在的线程结果:


2014-12-27 11:09:18.414 networktest[1133:417103] ------<NSThread: 0x14e4a120>{number = 1, name = main}------nnnn


   要使用NSOperation创建新线程这里还要用到NSOperationQueue,一看名字就知道他是一个队列,它是一个FIFO(First In First Out 先进先出)队列;它的底层是一个线程池,由于它是FIFO队列;因此被提交到这个队列点任务都是先提交到先开始被执行,注意这里只是先被执行,但不是先被执行完成,也就是说有可能有的线程任务比较耗时,因此,即使先被执行,也有可能最后完成的;这里的意思就是NSOperationQueue先进先出与线程的并发与否无关,它只保证最先提交对线程任务最先开始执行,而不保证每个线程任务执行完成的顺序。
我们看看NSOperation与NSOperationQueue是如何结合使用的:

-(void)startOPerationThread{

NSOperationQueue *queue=[[NSOperationQueue alloc] init];

    queue.maxConcurrentOperationCount=3;//设置当前最大工作线程数目

    NSInvocationOperation *operation=[[NSInvocationOperation allocinitWithTarget:selfselector:@selector(run1:) object:@"nnnn"];

    [queue addOperation:operation];//添加第一个任务

    NSBlockOperation *operation=[NSBlockOperation blockOperationWithBlock:^(void){

        NSLog(@"------%@------",[NSThread currentThread]);

    }];

    [queue addOperation:operation];//添加第二个任务

}

-(void)run1:(NSString *)n{

    NSLog(@"------%@------%@",[NSThread currentThread],n);

}


自定义NSOperation的子类:

@interface MyOperation : NSOperation

@end


@implementation MyOperation

-(void)main{

    NSLog(@"ddd-----%@",[NSThread currentThread]);

}

@end


使用自定义的NSOperation子类:

-(void)startMyOperation{

    MyOperation *operation=[[MyOperation alloc] init];

    [queue addOperation:operation];

}


   有趣的是我发现在java里面这么一段描述:这个线程池底层维护一个线程队列;而在Object-C里面是这样描述:这个队列底层维护一个线程池;嘿嘿,实现方面可能略有不同,但感觉其实都是线程池的功能;


3.GCD(Grand Central Dispatch)方式

关于GCD就不写了,这里引用一篇网友写的文章吧

GCD介绍(一)


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值