多线程的方式:
有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 alloc] initWithTarget: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
-(void)startOPerationThread{
NSOperationQueue *queue=[[NSOperationQueue alloc] init];
queue.maxConcurrentOperationCount=3;//设置当前最大工作线程数目
NSInvocationOperation *operation=[[NSInvocationOperation alloc] initWithTarget: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就不写了,这里引用一篇网友写的文章吧