ios平台下并发编程的研究和实现毕业论文(编辑修改稿)内容摘要:

er。 main:(可选)这个方法通常用于实现操作对象相应的任务。 尽管可 以 在 start 方法中实现这些任务,但是将其转移到这里会有较好的代码 结构 , 使得 操作对象的准备工作和执行阶段分开。 isExecuting、 isFinished:(必须)并发操作应该建立运行环境并且报告状态给外面的用户,然而,一个并发操作必须维护 一些 状态信息,来了解何时开启任务, 何时完成任务。 这些方法的实现必须是线程安全的,可能与 KVO 有关 [4]。 isConcurrent:重载并且返回 YES 即可。 下面 的代码示例简单的实现了如何子类化一个并发的操作对象: // 子类化 NSOperation @interface MyOperation: NSOperation { BOOL executing。 BOOL finished。 } (void)pleteOperation。 @end @implementation MyOperation // 实现 初始化方法 (id)init { self = [super init]。 if (self) { executing = NO。 finished = NO。 } return self。 } // 重载 操作对象的并发性属性 (BOOL)isConcurrent { return YES。 } // 重载 实现 KVO (BOOL)isExecuting { return executing。 } (BOOL)isFinished { return finished。 } 下面 的代码示 例为如何在 start 方法中 做 准备工作, 以及 实现 KVO: (void)start { 武汉工程大学 毕业论文 10 // 周期性 的检查是否有取消操作发生 if ([self isCancelled]) { // 如果 当前操作对象被取消,那么需要改变 finished 状态信息 [self willChangeValueForKey:@”isFinished”]。 finished = YES。 [self didChangeValueForKey:@”isFinished”]。 // 当 取消操作发生时, 需要 直接返回 return。 } // 当 操作对象没有被取消时, 开始 执行任务 [self willChangeValueForKey:@”isExecuting”]。 // 开启单独 的 线程 并执行任务 [NSThread detachNewThreadSelector:@selector(main) toTarget:self withObject:nil]。 // 这个 时候任务已经开始了, 需要 改变 executing状态 executing = YES。 [self didChangeValueForKey:@”isExecuting”]。 } 当 编写完操作对象的准备阶段的 start 方法后, 就 可以开始编写 main方法, 将 start方法和 main方法 分开 使得 代码有清晰的结构, 有助于 调试和 Debug。 在 main方法 中,当 操作对象的状态改变时, 仍需 实现对象的 KVO 规则, 如下 : (void)main { @try { // 开始 执行有关操作的 主任务 // 执行完成 后调用完成操作 [self pleteOperation]。 } @catch(… ) { // 仍然 无需 抛出异常 } } (void)pleteOperation { [self willChangeValueForKey:@”isFinished”]。 [self willChangeValueForKey:@”isExecuting”]。 // 在 任务完成后, 需要 更改对 应 的状态信息 executing = NO。 finished = YES。 [self didChangeValueForKey:@” isFinished”]。 [self didChangeValueForKey:@” isExecuting”]。 } 保证 KVO 规则 NSOperation 对于以下属性实现 KVO: isCancelled、 isConcurrent、 isExecuting、isFinished、 isReady、 dependencies、 queuePriority、 pletionBlock。 如果对 NSOperation重 写了 start 方法或者做了其他一些重大的定制,除了重载 main武汉工程大学 毕业论文 11 方法,还需要确保自定义对象仍然保证了 KVO 规则。 如果想要实现对其他操作 对象 依赖项的支持,可以重载 isReady 方法,直到自定义的依赖项已经 满足,不然一直返回 NO(这里应该调用 super),当状态改变时,通过发出 KVO 通知告知状态的改变。 除非你重写 addDependency 或 removeDependency 方法,不然无需 操心 dependencies 的 KVO 规则 [5]。 尽管可以生成其他 key 的 KVO,但是最好不要这样做。 如果 需要 取消操作对象,只需调用其 cancel 方法即可,同样,整个过程可能不需要修改队列优先级。 最后,除非操作对象会动态改变 isConcurrent 属性,不然无需实现其 KVO 规则。 自定义操作 对象 的执行行为 成功建 操作对象后,在将其添加到队列之前,可以对操作对象进行配置。 这一节中所描述的配置类型既可以应用于自定义的继承于 NSOperation类 的子类,也可应用于系统提供的子类。 配置操作对象之间的依赖关系 依赖关系是一种序列化不同操作对象的方式。 一个对象依赖于其他对象的执行状态,只有当其依赖的对象全部完成时,它自己才可以开始执行。 因此,可以使用依赖关系来创立复杂的执行顺序。 使用 NSOperation 类 的 addDependency:方法创建两个对象之间的依赖关系。 这个方法创建一个从当前对象到目标对象单向的依 赖关系,其返回结果可以作为一个参数来传递。 这种依赖性表示当前的对象只有在目标对象完成时才可以开始执行。 这种依赖关系并不局限于同一个队列中的操作对象,因为操作对象本身管理自己的依赖项,所以,完全可以在不同队列中的不同操作对象之间创建依赖关系。 需要注意的是,不要产生循环依赖的关系。 当所有的依赖项都已经完成时,当前操作对象将准备开始执行(当重载 isReady 方法后,这个状态需要使用自己创建的标准)。 如果对象已经处于队列中,那么队列可能随时开始执行这个对象,如果 是 手动管理对象的执行,那么需要调用操作对象的 start方法。 应该总是在操作对象运行之前或者添加到队列之前配置它的依赖关系, 在 运行之后添加依赖关系可能会无效。 依赖关系依赖于每个对象当状态变化时发送 KVO 通知,当自定义对象的这种行为时,为了避免出错,可能需要在代码中生成对应的 KVO 通知。 更改操作执行的优先级 对于添加到队列的 操作对象 ,执行顺序首先取决于已经入队操作对象的准备情况,然后取决于其优先级。 准备情况取决于操作对象依赖的其他对象,但是优先级是操作对武汉工程大学 毕业论文 12 象自身的属性,默认情况下,所有新创建的操作对象都有一个默认的优先级,但可以通过 setQueuePriority方法增大或者减 小 优先级。 优先级只适用于同一个队列中的不同对象,如果程序中有多个操作队列,每个对象在不同的队列中的优先级是相互独立的。 因此,低优先级的操作对象可能在不同的队列中执行 得 比高优先级的操作对象要早。 优先级不是依赖关系的替代,优先级只 影响 某个队列中已经做好执行准备的操作对象,举个例子,如果一个队列中,存在已经准备好的两个不同优先级的对象,那么首先执行高优先级的,但如果高优先级的还未准备好,低优先级的已经准备好了,那么首先会执行低优先级的,如果想要使某个操作对象必须在另一个操作对象执 行完毕之后才执行,那么应该使用依赖关系而不是优先级。 开始执行操作对象 当操作对象初始化并且配置完成后,需要执行它们来完成程序中的工作。 更改操作执行的优先级 到目前为止,执行操作对象最简单的方式就是将其添加到一个操作队列,应用程序本身负责创建和维护需要使用的操作队列。 程序可以拥有多个操作队列,但 如果 太多会有限制。 操作队列 与 系统根据内核和系统负载,决定某一时刻维持多少并发的数量,因此,创建太多的操作队列不一定能够立即执行其中的操作对象。 创建队列与创建其他对象的方式一样。 可以使用 addOperation:方法添加操作对象,同时还可以使用 addOperationWithBlock:方法添加 block,所有这些方法均进队一个操作对象并开始执行。 大多数情况下,操作对象会在添加到队列后就开始执行,但是仍然还有其他一些原因可能会导致操作对象被推迟执行。 例如某个操作对象依赖于其他操作对象的完成,或者操作队列本身是被挂起的,亦或是操作数超过了队列设置的最大并发数。 一定要注意当操作对象添加到操作队列后,不能去改变它,你可以使用 NSOperation类的其他方法来查看它当前的状态。 尽管操作队列是并发的,但 是仍然可以通过设置其最大并发数为 1 使其强制串行执行,尽管同一时间只有一个操作对象执行,但是其执行顺序仍然受其他因素的影响,因此串行的操作队列并不能提供像 GCD 一样的行为,如果串行队列中操作对象之 间 的执行顺序很重要,那么使用依赖关系仍然是最适合的方式。 手动实行操作对象 尽管操作队列可以很方便 地 执行操作对象,但是有时候仍希望不通过操作队列来执行某些操作对象,下面是一些手动执行需要注意的地方,最重要的是必须要保证其准备好执行 然后 调用其 start 方法。 武汉工程大学 毕业论文 13 操作对象不会 在 isReady 方法返回 YES 之前执行 , isReady 方法取决于其依赖的对象是否全部执行完毕。 手动执行时必须显示调用其 start 方法,不能使用 main或者其他方法,因为 start 方法在真正运行前做了一些检查,尤其是 start 方法中实现了有关 KVO 通知的生成,保证了其他对象正确的依赖 状态 ,此方法同时还保证了在取消之后不去执行或者没有准备好执行时抛出异常。 如果程序中定义了一些并发的操作对象, 那么 应该考虑在加载之前调用其isConcurrent 方法,当它返回 NO 时,就能够决定是在当前线程同步执行操作对象还是开启另一个线程。 下面的例子简单的示范了 手动执行操作 对象 时的一些检查工作, 当 方法返回 NO时,应该 考虑实现定时器来重复调用直到返回 YES。 (BOOL)performOperation:(NSOperation *)anOp { BOOL ranIt = NO。 // 检查 操作对象的状态 if ([anOp isReady] amp。 amp。 ![anOp isCancelled]) { // 当操作 对象准备好并且没有被取消时 if(![anOp isConcurrent]) { // 操作 对象为串行执行时, 直接 调用 start 方法 [anOp start]。 }else { [NSThread detachNewThreadSelector:@selector(start) toTarget:anOp withObject:nil]。 } ranIt = YES。 }else if ([anOp isCancelled]) { // 操作对象 被取消, 需要 发出 KVO 通知并且 改变 执行状态 [self willChangeValueForKey:@”isFinished”]。 [self willChangeValueForKey:@”isExecuting”]。 executing = NO。 finished = YES。 [self didChangeValueForKey:@” isFinished”]。 [self didChangeValueForKey:@” isExecuting”]。 ranIt = YES。 } return ranIt。 } 取消 操作对象的执行 一旦 操作对象添加到操作队列后,将由操作队列高效 地 管理并且不能被移除,唯一出队的方式就是取消它,可以通过调用其 cancel 方法取消单个的操作对象,也可以调 用操作队列的 cancelAllOperation 方法取消队列中所有的操作对象。 武汉工程大学 毕业论文 14 只有在确定不再需要时才取消它,取消其实相当于操作对象已经完成,如果被依赖项被取消,那么这个依赖关系就不再成立了。 等待 操作 对象执行完成 为了 程序 有更出色 的 表现,应该让操作对象尽可能的并发, 好让 程序能够去做别的事情,如果创建。
阅读剩余 0%
本站所有文章资讯、展示的图片素材等内容均为注册用户上传(部分报媒/平媒内容转载自网络合作媒体),仅供学习参考。 用户通过本站上传、发布的任何内容的知识产权归属用户或原始著作权人所有。如有侵犯您的版权,请联系我们反馈本站将在三个工作日内改正。