现在,我将会向你更深入的介绍如何使用之前提到的方法来创建新的operations。
NSInvocationOperation
当一个新的NSInvocationOperation对象创建时,它是用来运行指定的一个方法。你可能会想要使用这个对象,如果
在你的应用中你想避免创建过多的自定义operation类。
你正在添加或维护一个已经存在的应用,而它的类都已经定义好了,同时你不想修改NSOperation的子类。
selector能够根据用户的输入进行改变。在这种情况下,你只需要用一个已经选择好的selector创建一个新的NSInvocationOperation对象。
创建一个NSInvocationOperation对象的代码如下:
NSInvocationOperation* theOp = [[NSInvocationOperation alloc] initWithTarget:self
selector:@selector(myTaskMethod:) object:data];
这个和使用NSThread创建和detach一个新的线程类似。你传递一个目标对象,你想要调用的selector,还有在执行时selector想要使用的参数。
NSBlockOperation
NSBlockOperation是NSOperation的另一个子类。当你创建一个block operation时,你必须在这个operation 对象内至少添加一个block。之后你可以在这个operation对象内添加更多的block来执行。当operation queue执行这个block operation时,它会在这个block operation结束之前执行这个block operation内的所有blocks。因此,你可以使用这个operation对象来跟踪一组blocks,然后你可以合并会处理相关结果。
创建一个block operation对象,你可以使用下面的代码:
NSBlockOperation* theOp = [NSBlockOperation blockOperationWithBlock: ^{
NSLog(@"Beginning operation.\n");
// Do some work.
}];
然后你可以在这个operation中添加另一个block:
[theOp addExecutionBlock:[NSBlockOperation blockOperationWithBlock: ^{
NSLog(@"Beginning operation.\n");
// Do some work.
}];
NSOperation
NSOperation是用来被继承的一个类。要继承NSOperation,你可以使用两种推荐的方法来创建。
自定义初始化方法:可以在这个类中接收数据和进行一些必要的逻辑处理。例如,你可以在init方法中接收一个url来下载图片,类似这样:
- (id)initWithData:(id)data {
if ((self = [super init]))
myData = data;
return self;
}
main方法:这是一个必须的方法,当任务启动时被调用。
为了得到一个并发的NSOperation子类,你必须重写更多的方法来帮助NSOperationQueue对象来处理调用者的多线程请求。
start或main:你需要重写这个方法或main方法,当线程启动你的operations时,能够执行你的逻辑。默认,这个方法没有做任何事情,除了调用main方法。因此,你可以重写这个方法或main方法。
isExecuting或isFinished:你的operation需要报告它当前的状态给外面的客户端。有两个最重要的状态就是:你的operation已经开始执行,你的operation已经执行完毕。因此你需要在这里通过使用属性或实例变量来跟踪和报告这些状态。
isConcurrent:你必须重写这个方法,然后返回YES。
其他方法不是强制性的,但是你可能经常会需要他们。
其他逻辑处理方法:除非你想把所有的代码都放在main方法中,你同样需要其他的方法来包含你的逻辑处理代码。
Listing 6-4 显示了一个自定义和并发的NSOperation类的完整代码。
Listing 6-4 展示了如何编写一个自定义的NSOperation,使用多线程来从网络下载一张图片。
注意:如果你之前做过java编程,你会发现NSOperation和Thread类或Runnable接口很像。在Thread类中,你可以继承Thread类,然后重写run方法。对于Runnable接口也一样,你需要实现Runnable接口,然后重写run方法。你可以看到,NSoperation的main方法和Thread类,Runnable接口的run方法是一样的。 |
配置一个线程
你可以使用一些选项来配置你的线程,这样你就可以使用系统资源而不需要重载他们,尤其是在受限的运行时环境中,比如iPhone。
栈的大小:无论何时创建一个线程,OS会给线程的栈分配一个默认大小的内存来执行。如果你不知道栈是什么,你可以查看第5章。线程内部的栈会保存局部变量和线程执行时的方法。为了设置线程的栈大小,你需要在detaching线程之前设置。对于NSThread,这意味着你要使用初始化方法:
NSThread* myThread = [[NSThread alloc]initWithTarget:self
selector:@selector(myThreadMainMethod:)object:nil];
[myThread setStackSize:40960]; // 40KB here, the size is in bytes and multiple of 4KB
[myThread start]; // Actually create the thread
线程局部存储:没一个线程都有一个键值对的字典来存储数据,它能够在线程内部的任何地方访问。你可以使用这个字典来存储数据,还可以垮线程来呈现数据,而不需要在代码中创建全局变量。你可以使用[aThread threadDictionary]来调用字典。
线程优先级:线程优先级就是OS选择哪个线程来执行的可能性。优先级越高,线程运行的可能性就越大。但是,优先级并不能向你保证任何事情,在OS切换到其他线程之前。它同样不能保证一个高优先级的线程总是被选中,相对于低优先级的线程来说。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。