iOS 多线程详解

一:operations(任务)

cocoa提供了三种不同的operations

1:Block operations(NSBlockOperation
These facilitate the execution of one ormore block objects.

代码
#import   
@interface OperationsAppDelegate : NSObject  {  
    UIWindow *window;  
    NSBlockOperation *simpleOperation;  
}  
  
@property (nonatomic, retain) IBOutlet UIWindow *window;  
@property (nonatomic, retain) NSBlockOperation *simpleOperation;  
  
@end  

 代码  

#import "OperationsAppDelegate.h"  
  
@implementation OperationsAppDelegate  
@synthesize window;  
@synthesize simpleOperation;  
  
- (BOOL) application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {  
      
    NSBlockOperation *newBlockOperation = [NSBlockOperation blockOperationWithBlock:^{  
                            NSLog(@"Main Thread = %@", [NSThread mainThread]);  
                            NSLog(@"Current Thread = %@", [NSThread currentThread]);  
                            NSUInteger counter = 0;  
                            for (counter = 0;counter < 1000;counter++){  
                                NSLog(@"Count = %lu", (unsigned long)counter);  
                            }  
                                }];  
  
      
    self.simpleOperation = newBlockOperation;  
      
      
    [self.simpleOperation start];  
  
      
      
    NSLog(@"Main thread is here");  
    [window makeKeyAndVisible];  
    return YES;  
}  
  
  
- (void)dealloc {  
    [simpleOperation release];  
    [window release];  
    [super dealloc];  
}  
  
@end
 
2:Invocationoperations( NSInvocationOperation
These allow you to invoke a method in another, currently existingobject.

 

NSNumber *simpleObject = [NSNumber numberWithInteger:123];

NSInvocationOperation *newOperation = [[NSInvocationOperationalloc] initWithTarget:selfselector:@selector(simpleOperationEntry:) object:simpleObject];

[newOperation  start];

调用start方法执行改任务

代码 

#import   
@interface OperationsAppDelegate : NSObject  {  
    UIWindow *window;  
    NSInvocationOperation *simpleOperation;  
}  
  
@property (nonatomic, retain) IBOutlet UIWindow *window;  
@property (nonatomic, retain) NSInvocationOperation *simpleOperation;  
  
@end 
 

 代码 

- (void) simpleOperationEntry:(id)paramObject{  
  
    NSLog(@"Parameter Object = %@", paramObject);  
    NSLog(@"Main Thread = %@", [NSThread mainThread]);  
    NSLog(@"Current Thread = %@", [NSThread currentThread]);  
}  
  
- (BOOL) application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {  
  
    NSNumber *simpleObject = [NSNumber numberWithInteger:123];  
    NSInvocationOperation *newOperation =[[NSInvocationOperation alloc] initWithTarget:self selector:@selector(simpleOperationEntry:) object:simpleObject];  
    self.simpleOperation = newOperation;  
    [newOperation release];  
  
    [self.simpleOperation start];  
    [window makeKeyAndVisible];  
    return YES;  
}  
  
- (void)dealloc {  
  
    [simpleOperation release];  
    [window release];  
    [super dealloc];  
}  


3:Plain operations(简单的任务)NSOperation的子类


These are plain operation classes that need to be subclassed. Thecode to be executed
will be written inside the main methodof the operation object.


代码 

@interface MyTask : NSOperation {   
    int operationId;   
}  
  
@property int operationId;  
  
@end  


这里的operationId属性不是必须的


代码

@implementation MyTask  
  
@synthesize operationId;  
  
- (void)main{   
    NSLog(@"task %i run … ",operationId);   
    [NSThread sleepForTimeInterval:10];   
    NSLog(@"task %i is finished. ",operationId);   
}  
  
@end  

必须
- (void)main;方法,[MyTask start]是执行main方法


二:任务队列(NSOperationQueue)

NSOperationQueue *newOperationQueue = [[NSOperationQueue alloc]init];
[ newOperationQueue  addOperation:Operation];

以上三种Operation都可以添加到NSOperationQueue中,添加后立即被执行。

NSOperationQueue 可以设置最大并行执行任务数。默认值为-1无限制。

 

三:多个任务之间存在依赖关系

设置方式:

[self.firstOperationaddDependency:self.secondOperation];

dependency:附属的意思

把secondOperation做为firstOperation的附属。因此先执行secondOperation,再执行firstOperation。


四:延时执行某个方法

1:performSelector:withObject:afterDelay:

代码 
- (void) connectionHasFailedWithError:(NSError *)paramError onRemoteURL:(NSURL *)paramRemoteURL{  
      
    [self performSelector:@selector(attemptToDownloadRemoteURL:) withObject:paramRemoteURL afterDelay:3.0f];  
}  
  
- (void) attemptToDownloadRemoteURL:(NSURL *)paramRemoteURL{  
      
}  

 

该方法只能接受一个参数。如果需要传递多个参数怎么办呢???

    让selector调用的方法接受的参数类型修改为Dictionary类型。

(1)如果调用的selector不接受参数则,withObject:nil

(2) 通过performSelector:withObjcet:afterDelay调用的方法不能有返回值

2:取消延时执行的方法

(1)cancelPreviousPerformRequestsWithTarget: 

(2) cancelPreviousPerformRequestsWithTarget:selector:object:


五:NSTimer

1:scheduledTimerWithTimeInterval:target:selector:userInfo:repeats:

2:invalidate

调用invalidate方法,不仅是释放NSTimer,还释放userinfo对象。
如果repeats设置为NO,NSTimer在调用完成之后就知道失效,随即释放userinfo对象

3:scheduledTimerWithTimeInterval:invocation:repeats:

 代码  

- (void) startPainting{  
    SEL selectorToCall = @selector(paint:);  
    NSMethodSignature *methodSignature = [[self class] instanceMethodSignatureForSelector:selectorToCall];  
    NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:methodSignature];  
    [invocation setTarget:self];  
    [invocation setSelector:selectorToCall];  
  
  
NSTimer *newTimer =[NSTimer scheduledTimerWithTimeInterval:1.0  
                        invocation:invocation  
                           repeats:YES];  
  
    self.paintingTimer = newTimer;  
} 


 4:timerWithTimeInterval:target:selector:userInfo:repeats:

  (用该方式,需要把timer添加到runloop中)

 代码 

- (void) startPainting{  
    NSTimer *newTimer = [NSTimer timerWithTimeInterval:1.0  
                            target:self  
                          selector:@selector(paint:)  
                          userInfo:nil  
                           repeats:YES];  
  
    self.paintingTimer = newTimer;  
  
    [[NSRunLoop currentRunLoop] addTimer:self.paintingTimer forMode:NSDefaultRunLoopMode];  
}  
 

5:timerWithTimeInterval:invocation:repeats:

 (用该方式,需要把timer添加到runloop中)

代码  

 

- (void) startPainting{   
    SEL selectorToCall = @selector(paint:);  
    NSMethodSignature *methodSignature =[[self class] instanceMethodSignatureForSelector:selectorToCall];  
    NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:methodSignature];  
  
    [invocation setTarget:self];  
    [invocation setSelector:selectorToCall];  
    NSTimer *newTimer = [NSTimer timerWithTimeInterval:1.0  
                        invocation:invocation  
                           repeats:YES];  
    self.paintingTimer = newTimer;  
    [[NSRunLoop currentRunLoop] addTimer:self.paintingTimer  
                     forMode:NSDefaultRunLoopMode];  
}  

6:NSTimer 响应函数定义格式

 

并需有一个NSTimer *类型的参数

 代码  

- (void) paint:(NSTimer *)paramTimer{  
      
    NSLog(@"Painting");  
}
 

六:NSThread

1:initWithTarget:selector:object:

2:detachNewThreadSelector:toTarget: withObject:

以上两种方式,selector调用的函数,必须声明自己的NSAutoreleasePool

3:performSelectorInBackground: withObject:

    一个简单的方法来创建线程,而无需直接处理线程。

代码  

  [self performSelectorInBackground:@selector(thirdCounter) withObject:nil];  

4:start

调用start方法启动线程

5:cancel

调用cancel方法,并把变量赋值为nil

6:cancel vs exit

对于线程调用cancel方法停止,不要调用exit,因为exit方法没有给线程清理自己并释放资源的时间

7:线程的内存泄露

 代码  

- (void) newThreadEntryPoint{  
      
    //NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];  
      
      
    [self performSelector:@selector(allocateSomething)];  
  
      
    [self performSelectorOnMainThread:@selector(allocateSomething)  
                withObject:nil  
                 waitUntilDone:YES];  
    //[pool release];  
}  
  
- (void) allocateSomething{  
    NSBundle *mainBundle = [NSBundle mainBundle];  
    NSString *imagePath = [mainBundle pathForResource:@"MyImage" ofType:@"png"];  
    NSData *imageData = [NSData dataWithContentsOfFile:imagePath];  
    UIImage *myImage = [[[UIImage alloc] initWithData:imageData] autorelease];  
      
}  
  
- (void)viewDidLoad {  
  
    [NSThread detachNewThreadSelector:@selector(newThreadEntryPoint)  
                 toTarget:self  
                   withObject:nil];  
}  


UIImage *myImage = [[[UIImage alloc] initWithData:imageData]autorelease];-------------自动释放池的范围

[self performSelector:@selector(allocateSomething)];

调用改方法myImage 对象被添加进该新建线程的自动释放池,但因为在这里没有声明NSAutoreleasePool造成内存泄露

[selfperformSelectorOnMainThread:@selector(allocateSomething)
withObject:nil
    waitUntilDone:YES];

调用改方法myImage 对象被放进主线程的自动释放池,在主线程销毁是被自动释放


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值