多线程在各种编程语言中都是难点,很多语言中实现起来很麻烦,objective-c虽然源于c,但其多线程编程却相当简单,可以与java相媲美。这篇文章主要从线程创建与启动、线程的同步与锁、线程的交互、线程池等等四个方面简单的讲解一下iphone中的多线程编程。

一、线程创建与启动

线程创建主要有三种方式:

- (id)init; // designated initializer
- (id)initWithTarget:(id)target selector:(SEL)selector object:(id)argument; 这两种方法创建后,需要手机启动,启动的方法是: - (void)start; 当然,还有一种比较特殊,就是使用所谓的convenient method,这个方法可以直接生成一个线程并启动它,而且无需为线程的清理负责。这个方法的接口是: + (void)detachNewThreadSelector:(SEL)aSelector toTarget:(id)aTarget withObject:(id)anArgument 还有利用 NSObject 的类方法 performSelectorInBackground:withObject: 来创建一个线程: [myObj performSelectorInBackground:@selector(myThreadMainMethod) withObject:nil]; 二、线程的同步与锁
要说明线程的同步与锁,最好的例子可能就是多个窗口同时售票的售票系统了。我们知道在java中,使用synchronized来同步,而iphone虽然没有提供类似java下的synchronized关键字,但提供了NSCondition对象接口。查看NSCondition的接口说明可以看出,NSCondition是iphone下的锁对象,所以我们可以使用NSCondition实现iphone中的线程安全。这是来源于网上的一个例子:
SellTicketsAppDelegate.h 文件 // SellTicketsAppDelegate.h
#import <UIKit/UIKit.h> @interface SellTicketsAppDelegate : NSObject <UIApplicationDelegate> {
int tickets;
int count;
NSThread* ticketsThreadone;
NSThread* ticketsThreadtwo;
NSCondition* ticketsCondition;
UIWindow *window;
}
@property (nonatomic, retain) IBOutlet UIWindow *window;
@end SellTicketsAppDelegate.m 文件 // SellTicketsAppDelegate.m
#import "SellTicketsAppDelegate.h" @implementation SellTicketsAppDelegate
@synthesize window; - (void)applicationDidFinishLaunching:(UIApplication *)application {
tickets = ;
count = ;
// 锁对象
ticketCondition = [[NSCondition alloc] init];
ticketsThreadone = [[NSThread alloc] initWithTarget:self selector:@selector(run) object:nil];
[ticketsThreadone setName:@"Thread-1"];
[ticketsThreadone start]; ticketsThreadtwo = [[NSThread alloc] initWithTarget:self selector:@selector(run) object:nil];
[ticketsThreadtwo setName:@"Thread-2"];
[ticketsThreadtwo start];
//[NSThread detachNewThreadSelector:@selector(run) toTarget:self withObject:nil];
// Override point for customization after application launch
[window makeKeyAndVisible]; } - (void)run{
while (TRUE) {
// 上锁
[ticketsCondition lock];
if(tickets > ){
[NSThread sleepForTimeInterval:0.5];
count = - tickets;
NSLog(@"当前票数是:%d,售出:%d,线程名:%@",tickets,count,[[NSThread currentThread] name]);
tickets--;
}else{
break;
}
[ticketsCondition unlock];
}
} - (void)dealloc {
[ticketsThreadone release];
[ticketsThreadtwo release];
[ticketsCondition release];
[window release];
[super dealloc];
}
@end 三、线程的交互
线程在运行过程中,可能需要与其它线程进行通信,如在主线程中修改界面等等,可以使用如下接口: - (void)performSelectorOnMainThread:(SEL)aSelector withObject:(id)arg waitUntilDone:(BOOL)wait 由于在本过程中,可能需要释放一些资源,则需要使用NSAutoreleasePool来进行管理,如: - (void)startTheBackgroundJob {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
// to do something in your thread job
...
[self performSelectorOnMainThread:@selector(makeMyProgressBarMoving) withObject:nil waitUntilDone:NO];
[pool release];
} iOS4 已经支持多线程了,我的EASYWEB在打开多个网页时会卡得要命,决定把它改成多线程方式进行加载网页
iOS4的多线程,基于Objective-c 相对 C++ JAVA来说简单不少 技术要点:
一 线程创建与启动
线程类 NSThread 包含如下线程操作方法: //返回当前线程
+ (NSThread *)currentThread; // 通过类方法创建一个线程
+ (void)detachNewThreadSelector:(SEL)selector toTarget:(id)target withObject:(id)argument; // 判断是否为多线程
+ (BOOL)isMultiThreaded; - (NSMutableDictionary *)threadDictionary; + (void)sleepUntilDate:(NSDate *)date; + (void)sleepForTimeInterval:(NSTimeInterval)ti; // 退出线程
+ (void)exit; // 线程属性值
+ (double)threadPriority ;
+ (BOOL)setThreadPriority:(double)p ; // 线程函数地址
+ (NSArray *)callStackReturnAddresses; // 设置与返回线程名称
- (void)setName:(NSString *)n;
- (NSString *)name; // 线程堆栈
- (NSUInteger)stackSize;
- (void)setStackSize:(NSUInteger)s; // 判断当前线程是否为主线程
- (BOOL)isMainThread;
+ (BOOL)isMainThread; + (NSThread *)mainThread; // 线程对象初始化操作 (通过创建线程对象 ,需要 手工指定线程函数与各种属性)
- (id)init; // 在线程对象初始化时创建一个线程(指定线程函数)
- (id)initWithTarget:(id)target selector:(SEL)selector object:(id)argument; // 是否在执行
- (BOOL)isExecuting; // 是否已经结束
- (BOOL)isFinished; // 是否取消的
- (BOOL)isCancelled; // 取消操作
- (void)cancel; // 线程启动
- (void)start; - (void)main; // thread body method 推荐方式 推荐:iOS线程同步 [线程同步 提到多线程大家肯定会提到锁,其实真正应该说的是多线程同步,锁只是多线程同步的一部分。 多线程对于数据处理等方面有着优异的表现和性能,然后多线程如果存在 // 通过类方法创建一个线程
+ (void)detachNewThreadSelector:(SEL)selector toTarget:(id)target withObject:(id)argument; // 在线程对象初始化时创建一个线程(指定线程函数)
- (id)initWithTarget:(id)target selector:(SEL)selector object:(id)argument; 主要通过selector:(SEL)selector 指定个功能函数,系统使其与主线程分开运行,以达到多线程的效果. 以上方式创建线程,非类方法创建需要调用 start才能让线程真正运行起来. 当多个线程同时运行,就会出现访问资源的同步问题 二 线程同步操作 IPHONE 使用NSCondition来进行线程同步,它是IPHONE的锁对象,用来保护当前访问的资源. 大致使用方法 NSCondition* mYLock = [[NSCondition alloc] init]; [mYLock lock] 资源…. [mYLock unLock]; [mYLock release]; 三 线程的交互 使用线程对象的 - (void)performSelectorOnMainThread:(SEL)aSelector withObject:(id)arg waitUntilDone:(BOOL)wait 进行交互操作
主要是调用 主线程中指定的方法来执行一些相关操作 四 线程池 NSOperation
NSInvocationOperation是 NSOperation的子类 具体使用代码 // 建立一个操作对象
NSInvocationOperation* theOp = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(myTaskMethod:) object:data]; // 将操作对象 加到系统已经的操作对列里, 这时候 myTaskMethod以一个线程的方式与主线程分开执行.
[[MyAppDelegate sharedOperationQueue] addOperation:theOp]; // 这个是真正运行在另外一个线程的“方法”
- (void)myTaskMethod:(id)data
{
// Perform the task.
} 以上是使用系统操作对列,可以使用 NSOperationQueue创建自己的线程对列 NSOperationQueue *operationQueue;
operationQueue = [[NSOperationQueue alloc] init]; //初始化操作队列
[operationQueue setMaxConcurrentOperationCount:n]; // 可以设置队列的个数
[operationQueue addOperation:otherOper]; 线程创建与撤销遵循 OC的内存管理规则. 线程间通信,交互
,在应用程序主线程中做事情:
performSelectorOnMainThread:withObject:waitUntilDone:
performSelectorOnMainThread:withObject:waitUntilDone:modes:
,在指定线程中做事情: performSelector:onThread:withObject:waitUntilDone: performSelector:onThread:withObject:waitUntilDone:modes:
,在当前线程中做事情:
performSelector:withObject:afterDelay:
performSelector:withObject:afterDelay:inModes:
,取消发送给当前线程的某个消息
cancelPreviousPerformRequestsWithTarget:
cancelPreviousPerformRequestsWithTarget:selector:object:

iOS线程之——NSCondition的更多相关文章

  1. IOS 线程处理 子线程

    IOS 线程处理 子线程的启动与结束 技术交流新QQ群:414971585   IOS中,如果要在主线程中启动一个子线程,可以又两种方法: [NSThread detachNewThreadSelec ...

  2. iOS 线程操作库 PromiseKit

    iOS 线程操作库 PromiseKit 官网:http://promisekit.org/ github:https://github.com/mxcl/PromiseKit/tree/master ...

  3. iOS 线程安全--锁

    一,前言 线程安全是iOS开发中避免了的话题,随着多线程的使用,对于资源的竞争以及数据的操作都可能存在风险,所以有必要在操作时保证线程安全. 二,为什么要使用锁? 由于一个进程中不可避免的存在多线程, ...

  4. iOS 线程安全

    线程安全: 当多个线程访问同一块资源时,很容易引发数据错乱和数据安全问题.就好比几个人在同一时修改同一个表格,造成数据的错乱. 解决多线程安全问题的方法 方法一:互斥锁(同步锁) @synchroni ...

  5. iOS: 线程中那些常见的锁

    一.介绍 在多线程开发中,锁的使用基本必不可少,主要是为了解决资源共享时出现争夺而导致数据不一致的问题,也就是线程安全问题.锁的种类很多,在实际开发中,需要根据情况选择性的选取使用,毕竟使用锁也是消耗 ...

  6. ios线程和GCD

    1.什么是进程? 进程是指在系统中正在运行的一个应用程序.比如同时打开QQ.Xcode,系统就会分别启动2个进程.截图 2.什么是线程? 1).一个进程要想执行任务,必须得有线程(每一个进程至少要有一 ...

  7. iOS - 线程管理

    iOS开发多线程篇—GCD的常见用法 一.延迟执行 1.介绍 iOS常见的延时执行有2种方式 (1)调用NSObject的方法 [self performSelector:@selector(run) ...

  8. IOS线程的一些总结

    主线程的作用 (在主线程中才能设置) 显示/刷新UI界面 处理UI事件(比如点击事件.滚动事件.拖拽事件): 主线程的使用注意 别将比较耗时的操作放到主线程中. 耗时操作会卡住主线程.影响体验. [N ...

  9. iOS 线程锁同步机制

    转载自 http://yulingtianxia.com/blog/2015/11/01/More-than-you-want-to-know-about-synchronized/ 如果你已经使用 ...

随机推荐

  1. java对象转化成String类型

    在java项目的实际开发和应用中,常常需要用到将对象转为String这一基本功能.本文将对常用的转换方法进行一个总结.常用的方法有Object#toString(),(String)要转换的对象,St ...

  2. 手机联系人信息获取(contacts) ---- HTML5+

    模块:contacts Contacts模块管理系统通讯录,用于可对系统通讯录进行增.删.改.查等操作.通过plus.contacts获取系统通讯录管理对象. 对象:联系人对象(属性:电话,地址等)针 ...

  3. 网站微图标,页标签,favicon.ico

    随便打开一个网页:比如 http://www.baidu.com/ 可以看到在浏览器的标签头上面显示了一个图标,也就是我们常说的favicon.ico, 由于这篇文章主要讨论favicon.ico,以 ...

  4. angular-translate国际化

    1.<h1>{{"hello" | translate}}</h1>2.<h1 ng-bind-html="'hello' | transl ...

  5. Webservice实践(七)CXF 与Spring结合+tomcat发布

    上一节介绍了如何使用CXF 来发布服务,但是没有介绍使用web 容器来发布,很多项目需要用tomcat 这样的容器来发布.另外本节将介绍CXF 与spring 结合的方法. 一 目标: 1.利用spi ...

  6. centos shell脚本编程2 if 判断 case判断 shell脚本中的循环 for while shell中的函数 break continue test 命令 第三十六节课

    centos  shell脚本编程2 if 判断  case判断   shell脚本中的循环  for   while   shell中的函数  break  continue  test 命令   ...

  7. Spark 参数配置的几种方法

    1.Spark 属性Spark应用程序的运行是通过外部参数来控制的,参数的设置正确与否,好与坏会直接影响应用程序的性能,也就影响我们整个集群的性能.参数控制有以下方式:(1)直接设置在SparkCon ...

  8. HDU1452:Happy 2004(求因子和+分解质因子+逆元)上一题的简单版

    题目链接:传送门 题目要求:求S(2004^x)%29. 题目解析:因子和函数为乘性函数,所以首先质因子分解s(2004^x)=s(2^2*x)*s(3^x)*s(167^x); 因为2与29,166 ...

  9. 如何用 testNG 生成测试报告

    原文地址https://testerhome.com/topics/3473 总结一下testNG生成报告的三种方式,基本都是我直接转载的,没有补充就不说了,有补充的我会加以说明的(这里直说生成报告, ...

  10. pyenv常用命令

    pyenv使用教程 安装 Mac brew install pyenv brew install pyenv-virtualenv 配置 echo 'eval "$(pyenv init - ...