iOS 多线程详解

来源:互联网 发布:js 字符串等于 编辑:程序博客网 时间:2024/05/22 03:46

一: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
原创粉丝点击