iOS开发-多线程NSOperation和NSOperationQueue

简介:

上一篇文章稍微提及了一下NSThread的使用,NSThread能直观地控制线程对象,不过需要自己管理线程的生命周期,线程同步,用起来比较繁琐,而且比较容易出错。不过Apple给出了自己的解决方案NSOperation,它本身是抽象基类,因此必须使用它的子类,使用NSOperation子类的方式有NSInvocationOperation和NSBlockOperation两种方式,先补充一下NSThread的用法:

NSThread获取当前线程:

1
[ NSThread  currentThread]

 performSelectorInBackground可以更新UI,不建议使用:

1
2
3
4
5
- ( IBAction )update:( id )sender {
 
     [ self  performSelectorInBackground: @selector (changeImage) withObject: nil ];
     
}

图片背景更新:

1
2
3
4
-( void )changeImage{
     NSLog (@ "线程执行完之后更新图片" );
     self .myImageView.image=[UIImage imageNamed:[ NSString  stringWithFormat:@ "Thread2.jpg" ]];
}

NSInvocationOperation和NSBlockOperation

这两种方式都很简单,其中NSInvocation的调用方式类似于NSThread,NSBlockOperation如果对Block有一点了解就可以,如果不明白的可以参考本人之前的Block文章 Object-C-代码块Block回顾,那么接下来的使用方式就很简单:

先来看下NSInvocationOperation的实例化方式:

1
2
3
4
//初始化
NSInvocationOperation  *myInvocationOperation= [[ NSInvocationOperation  alloc] initWithTarget: self  selector: @selector (operationTaskMethod) object: nil ];
//启动
[myInvocationOperation start];

调用方法:

1
2
3
4
-( void )operationTaskMethod{
     NSLog (@ "NSInvocationOperation初始化执行" );
     
}

NSBlockOperation的方式:

1
2
3
4
NSBlockOperation  *blockOperation=[ NSBlockOperation  blockOperationWithBlock:^{
       NSLog (@ "BlockOperation块执行" );
   }];
   [blockOperation start];

两种方式很方便,这个时候可以使用NSOperationQueue作为一个队列将线程包含在一起,首先定义一个NSOperationQuene:

1
@property  (strong, nonatomic NSOperationQueue  *myOperationQuene;

 这个时候需要调用:

1
2
3
4
5
6
7
8
9
10
11
NSInvocationOperation  *myInvocationOperation= [[ NSInvocationOperation  alloc] initWithTarget: self  selector: @selector (operationTaskMethod) object: nil ];
 
NSBlockOperation  *blockOperation=[ NSBlockOperation  blockOperationWithBlock:^{
     NSLog (@ "BlockOperation块执行" );
}];
 
self .myOperationQuene=[[ NSOperationQueue  alloc]init];
 
[ self .myOperationQuene addOperation:myInvocationOperation];
 
[ self .myOperationQuene addOperation:blockOperation];

 上面最后的结果不确定,线程执行的顺序没法确定,如果想确定的按照顺序执行,需要添加一个依赖:

1
[blockOperation addDependency:myInvocationOperation];

  添加依赖之后的,每次输出的结果一定是这样的:

1
2
2015-02-11 07:56:13.457 ThreadDemo[657:15033]  NSInvocationOperation 初始化执行
2015-02-11 07:56:13.457 ThreadDemo[657:15034] BlockOperation块执行

 自定义NSOperation

每次一看到自定义,就感觉瞬间有了档次,然后参考一下前人的经验,不过网上的博客有的不好说,那感觉就是我想吃一个鸡腿,却拿到了一个鸡腿堡,需要的不需要的都要自己一起吸收。NSInvocationOperation和NSBlockOperation这两种方式不能满足业务需求,这个时候需要自定义的NSOperation,自定义的有两种分为非并发(NonConcurrent)和并发(Concurrent)两种形式,本文介绍非并发形式。

新建一个继承自NSOperation的MyCustomOperation,然后实现一下main方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//
//  MyCustomOperation.h
//  ThreadDemo
//
//  Created by keso on 15/2/11.
//  Copyright (c) 2015年 keso. All rights reserved.
//
 
#import <Foundation/Foundation.h>
 
@interface  MyCustomOperation :  NSOperation
 
@property  (strong, nonatomic NSString   *customdata;
 
-( void )initData:( NSString  *)data;
 
@end

NSOperation对象需要定期地调用isCancelled方法检测操作是否已经被取消,如果返回YES(表示已取消),则立即退出执行回收内存资源。所有NSOperation子类,一般用于代码比较容易终止的地方, 在循环的每次迭代过程中,如果每个迭代相对较长可能需要调用多次和没有执行工作之前调用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
//
//  MyCustomOperation.m
//  ThreadDemo
//
//  Created by keso on 15/2/10.
//  Copyright (c) 2015年 keso. All rights reserved.
//
 
#import "MyCustomOperation.h"
 
@implementation  MyCustomOperation
 
- ( void )initData:( NSString  *)data{
     if  ( self  ==[ super  init])
         _customdata= data;
}
- ( void )main {
     @try  {
         BOOL  isDone =  NO ;
         NSLog (@ "循环之前的调用" );
         while  (![ self  isCancelled] && !isDone) {
             // Do some work and set isDone to YES when finished
             NSLog (@ "已经运行成功了" );
             isDone= YES ;
         }
     }
     @catch (...) {
         NSLog (@ "出现异常,请检查代码~" );
     }
}
 
@end

如果需要调用定义的NSOPeration实例化之后Start即可:

1
2
MyCustomOperation *customOperation=[[MyCustomOperation alloc] init];
  [customOperation start];

本文转自Fly_Elephant博客园博客,原文链接:http://www.cnblogs.com/xiaofeixiang/p/4285102.html,如需转载请自行联系原作者

相关文章
|
11天前
|
iOS开发 开发者 MacOS
深入探索iOS开发中的SwiftUI框架
【10月更文挑战第21天】 本文将带领读者深入了解Apple最新推出的SwiftUI框架,这一革命性的用户界面构建工具为iOS开发者提供了一种声明式、高效且直观的方式来创建复杂的用户界面。通过分析SwiftUI的核心概念、主要特性以及在实际项目中的应用示例,我们将展示如何利用SwiftUI简化UI代码,提高开发效率,并保持应用程序的高性能和响应性。无论你是iOS开发的新手还是有经验的开发者,本文都将为你提供宝贵的见解和实用的指导。
98 66
|
22天前
|
开发框架 Android开发 iOS开发
安卓与iOS开发中的跨平台策略:一次编码,多平台部署
在移动应用开发的广阔天地中,安卓和iOS两大阵营各占一方。随着技术的发展,跨平台开发框架应运而生,它们承诺着“一次编码,到处运行”的便捷。本文将深入探讨跨平台开发的现状、挑战以及未来趋势,同时通过代码示例揭示跨平台工具的实际运用。
|
26天前
|
Java 调度 Android开发
安卓与iOS开发中的线程管理差异解析
在移动应用开发的广阔天地中,安卓和iOS两大平台各自拥有独特的魅力。如同东西方文化的差异,它们在处理多线程任务时也展现出不同的哲学。本文将带你穿梭于这两个平台之间,比较它们在线程管理上的核心理念、实现方式及性能考量,助你成为跨平台的编程高手。
|
28天前
|
存储 前端开发 Swift
探索iOS开发:从新手到专家的旅程
本文将带您领略iOS开发的奇妙之旅,从基础概念的理解到高级技巧的掌握,逐步深入iOS的世界。文章不仅分享技术知识,还鼓励读者在编程之路上保持好奇心和创新精神,实现个人成长与技术突破。
|
1月前
|
API Android开发 iOS开发
深入探索Android与iOS的多线程编程差异
在移动应用开发领域,多线程编程是提高应用性能和响应性的关键。本文将对比分析Android和iOS两大平台在多线程处理上的不同实现机制,探讨它们各自的优势与局限性,并通过实例展示如何在这两个平台上进行有效的多线程编程。通过深入了解这些差异,开发者可以更好地选择适合自己项目需求的技术和策略,从而优化应用的性能和用户体验。
|
1月前
|
安全 IDE Swift
探索iOS开发之旅:从初学者到专家
在这篇文章中,我们将一起踏上iOS开发的旅程,从基础概念的理解到深入掌握核心技术。无论你是编程新手还是希望提升技能的开发者,这里都有你需要的指南和启示。我们将通过实际案例和代码示例,展示如何构建一个功能齐全的iOS应用。准备好了吗?让我们一起开始吧!
|
5天前
|
NoSQL Redis
单线程传奇Redis,为何引入多线程?
Redis 4.0 引入多线程支持,主要用于后台对象删除、处理阻塞命令和网络 I/O 等操作,以提高并发性和性能。尽管如此,Redis 仍保留单线程执行模型处理客户端请求,确保高效性和简单性。多线程仅用于优化后台任务,如异步删除过期对象和分担读写操作,从而提升整体性能。
17 1
|
2月前
|
存储 消息中间件 资源调度
C++ 多线程之初识多线程
这篇文章介绍了C++多线程的基本概念,包括进程和线程的定义、并发的实现方式,以及如何在C++中创建和管理线程,包括使用`std::thread`库、线程的join和detach方法,并通过示例代码展示了如何创建和使用多线程。
60 1
|
2月前
|
Java 开发者
在Java多线程编程中,创建线程的方法有两种:继承Thread类和实现Runnable接口
【10月更文挑战第20天】在Java多线程编程中,创建线程的方法有两种:继承Thread类和实现Runnable接口。本文揭示了这两种方式的微妙差异和潜在陷阱,帮助你更好地理解和选择适合项目需求的线程创建方式。
33 3
|
2月前
|
Java 开发者
在Java多线程编程中,选择合适的线程创建方法至关重要
【10月更文挑战第20天】在Java多线程编程中,选择合适的线程创建方法至关重要。本文通过案例分析,探讨了继承Thread类和实现Runnable接口两种方法的优缺点及适用场景,帮助开发者做出明智的选择。
25 2