本文复制、参考自文章:iOS多线程编程之NSThread的使用  ,主要为了加强个人对知识的理解和记忆,不做他用。原作者声明:

著作权声明:本文由http://blog.csdn.net/totogo2010/原创,欢迎转载分享。请尊重作者劳动,转载时保留该声明和作者博客链接,谢谢!

这里对原作者的辛勤工作表示感谢!

1. 简介

1.1 iOS的多线程编程技术分类

(1)NSThread

(2) Cocoa NSOperation

(3) GCD (Grand Central Dispatch)

这三种方式从上到下,抽象层次逐渐增高,使用也越来越简单。

1.2 三种方式的优缺点

  优点   缺点
NSThread 轻量 需要自己管理线程的生命周期,线程同步。线程同步加锁时,会有一定的系统开销。
NSOperation   无需关心线程管理,数据同步,可以把精力放在自己需要的执行操作上  
GCD iOS4.0后出现,以替代NSThread,NSOperation等技术的,很高效、强大  

2. NSThread的使用

2.1 创建方式

(1) 实例方法创建

- (id) initWithTarget:(id)target selector:(SEL)selector object:(id) argument
示例:
NSThread* myThread = [[NSThread alloc] initWithTarget:self
selector:@selector(doSomething:)
object:nil];
[myThread start];

(2) NSThread 类方法创建

+ (void)detachNewThreadSelector:(SEL) aSelector toTarget:(id)aTarget withObject:(id)anArgument

示例:
[NSThread detachNewThreadSelector:@selector(doSomething:) toTarget:self withObject:nil];

(3)NSObject 非显示方法创建

+ (void) performSelectorInBackground:(SEL)aSelector withObject:(id)anArgument
示例
[Obj performSelectorInBackground:@selector(doSomething:)withObject:nil];

selector: 线程执行的方法,这个selector只能有一个参数,而且不能有返回值;

target:    selector消息发送的对象

argument:传输给selector的唯一参数,也可以是nil

第一种方式会直接创建线程并且开始运行线程,第二种方法是先创建线程对象,然后再运行线程操作,在运行线程操作前可以设置线程的优先级等线程信息。

2.2 使用示例1: 异步加载图片

(1)在viewDidLoad中创建子线程:

- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
NSThread* thread = [[NSThread alloc] initWithTarget:self selector:@selector(downloadImage:) object:kURL]; // 子线程执行方法 downloadImage
[thread start]; // 启用子线程
}

(2)在线程执行方法 downloadImage 中执行加载数据操作,并使用performSelectorOnMainThread方法 通知主线程进行渲染操作。(线程调回主线程,并传递了数据)

- (void)downloadImage:(NSString *) url
{
NSData* data = [[NSData alloc] initWithContentsOfURL:[NSURL URLWithString:url]];
UIImage* image = [[UIImage alloc] initWithData:data];
if(image == nil)
{
NSLog(@"image load failed...");
}
else
{
[self performSelectorOnMainThread:@selector(updateUI:) withObject:image waitUntilDone:YES]; // 与主线程通信,传递了image数据
}
}

同样,还可以使用:

- (void)performSelector:(SEL)aSelector  onThread:(NSThread *)thread   withObject:(id)arg    waitUntilDone:(BOOL)wait    modes:(NSArray *)array

方法来于其他线程通信。

2.3 使用示例2: 多线程卖票

(1) 定义public的数据结构,AppDelegate.h中

@interface AppDelegate : UIResponder <UIApplicationDelegate>
{
int tickets;
int count;
NSThread* ticketsThreadOne;
NSThread* ticketsThreadTwo;
NSCondition* ticketsCondition;
NSLock* theLock;
}

这里测试使用了NSCondition和NSLock两种加锁方法。

(2)初始化, AppDelegate.m中

    tickets = ;
count = ;
theLock = [[NSLock alloc] init];
// 锁对象
ticketsCondition = [[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];

(3)执行操作中,加锁,防止资源抢占

- (void)run
{
while (TRUE)
{
// 上锁
// [theLock lock];
[ticketsCondition lock];
if (tickets >= )
{
[NSThread sleepForTimeInterval:0.09];
count = -tickets;
NSLog(@"当前票数是:%d, 售出:%d, 线程名:%@", tickets, count, [[NSThread currentThread] name]);
tickets--;
}
else
{
break;
}
[ticketsCondition unlock];
// [theLock unlock];
}
}

NSCondition 可以使用 [ticketsCondition wait];等待,并由其他线程使用[ticketsCondition signal];唤起等待。

2.4 使用@synchoronized

我们还可以使用@synchoronized来简化NSLock的使用,这样就不必显示创建和调用NSLock对象,而自动创建了一个互斥锁(mutex lock),防止对资源的抢占。 如下

    obj1 = [[NSObject alloc]init]; // 两个线程,分别传递两个对象用于原操作标识
obj2 = [[NSObject alloc]init]; ticketsThreadOne = [[NSThread alloc] initWithTarget:self selector:@selector(run:) object:obj1];
[ticketsThreadOne setName:@"Thread-1"];
[ticketsThreadOne start]; ticketsThreadTwo = [[NSThread alloc] initWithTarget:self selector:@selector(run:) object:obj2];
[ticketsThreadTwo setName:@"Thread-2"];
[ticketsThreadTwo start];
- (void)run:(NSObject*) obj
{
@synchronized(obj)
{
while (TRUE)
{
// 上锁
// [theLock lock];
// [ticketsCondition lock];
int currentTicketNum = [ticketCounter currentTicketNum];
if ( currentTicketNum >= )
{
[NSThread sleepForTimeInterval:0.09];
NSLog(@"当前票数是:%d, 售出:%d, 线程名:%@", currentTicketNum, ticketCounter.initTicketNum - currentTicketNum, [[NSThread currentThread] name]);
ticketCounter.currentTicketNum--;
}
else
{
break;
}
// [ticketsCondition unlock];
// [theLock unlock];
}
}
}

iOS 多线程学习笔记 —— NSThread的更多相关文章

  1. iOS 多线程学习笔记 —— GCD

    本文复制.参考自文章:iOS多线程编程之Grand Central Dispatch(GCD)介绍和使用 ,主要为了加强个人对知识的理解和记忆,不做他用.原作者声明: 著作权声明:本文由http:// ...

  2. iOS 多线程学习笔记 —— NSOperation

    本文复制.参考自文章:iOS多线程编程之NSOperation和NSOperationQueue的使用 ,主要为了加强个人对知识的理解和记忆,不做他用.原作者声明: 著作权声明:本文由http://b ...

  3. java多线程学习笔记——详细

    一.线程类  1.新建状态(New):新创建了一个线程对象.        2.就绪状态(Runnable):线程对象创建后,其他线程调用了该对象的start()方法.该状态的线程位于可运行线程池中, ...

  4. JAVA多线程学习笔记(1)

    JAVA多线程学习笔记(1) 由于笔者使用markdown格式书写,后续copy到blog可能存在格式不美观的问题,本文的.mk文件已经上传到个人的github,会进行同步更新.github传送门 一 ...

  5. 多线程学习笔记九之ThreadLocal

    目录 多线程学习笔记九之ThreadLocal 简介 类结构 源码分析 ThreadLocalMap set(T value) get() remove() 为什么ThreadLocalMap的键是W ...

  6. java进阶-多线程学习笔记

    多线程学习笔记 1.什么是线程 操作系统中 打开一个程序就是一个进程 一个进程可以创建多个线程 现在系统中 系统调度的最小单元是线程 2.多线程有什么用? 发挥多核CPU的优势 如果使用多线程 将计算 ...

  7. Java多线程学习笔记(一)——多线程实现和安全问题

    1. 线程.进程.多线程: 进程是正在执行的程序,线程是进程中的代码执行,多线程就是在一个进程中有多个线程同时执行不同的任务,就像QQ,既可以开视频,又可以同时打字聊天. 2.线程的特点: 1.运行任 ...

  8. iOS多线程编程之NSThread的使用

      目录(?)[-] 简介 iOS有三种多线程编程的技术分别是 三种方式的有缺点介绍 NSThread的使用 NSThread 有两种直接创建方式 参数的意义 PS不显式创建线程的方法 下载图片的例子 ...

  9. iOS多线程编程之NSThread的使用(转)

    本文由http://blog.csdn.net/totogo2010/原创 1.简介: 1.1 iOS有三种多线程编程的技术,分别是: 1..NSThread 2.Cocoa NSOperation  ...

随机推荐

  1. 关于 ORA - 01861 文字与格式字符串不匹配问题(oracle存储过程)

    一般问题(TO_DATE 和 TO_CHAR 两种格式互换)比如: 只要转化下格式就OK ,这里就不详细解释这两种格式的用法了! 今天把之前做好的模块拿到当地实习,不管怎么测 ,连续测试了好几个存储过 ...

  2. [功能帮助类] C#取汉字拼音的首字母PinYin帮助类 (转载)

    点击下载 PinYin.rar 主要功能就是取汉字拼音的首字母,只要你输入一个汉字,或者是多个汉字就会取出相应的道字母,主要是方便查询使用的 /// <summary> /// 编 码 人 ...

  3. 计算机网络-ip地址聚合后可用的地址数

    (1)59.81.1.128/28=59.81.1.1000-0000(2)59.81.1.144/28=59.81.1.1001-0000(3)59.81.1.160/28=59.81.1.1010 ...

  4. android系统体系结构

    android系统底层是建立在Linux系统之上的,如下图 从上图可以看出android系统有五部分组成 1.APPLICATIONS(应用程序层) 包含一些核心应用程序,电子邮件,日历,地图,浏览器 ...

  5. xml处理相关文章收藏

    XPath语法 在C#中使用XPath示例:http://blog.csdn.net/yukaizhao/article/details/6630613 .Net那点事儿系列:C#操作Xml:通过Xm ...

  6. 第一章JSP基础语法

    jsp页面元素构成 jsp页面组成部分有:指令,注释,静态内容,表达式,小脚本,声明. jsp指令 page指令:通常位于jsp页面的顶端,同一个页面可以有多个page指令 include指令:将一个 ...

  7. artDialog.js的使用

    开发项目中用到了artDialog.js,从而专门学习一下如何配置和使用. 一.artDialog是什么 artDialog是一个精巧的web对话框组件,压缩后只有十多KB,并且不依赖其他框架. 二. ...

  8. gulp分享文档

    Grunt--I/O操作: 读取A → A.a() → 写出A → 读取A → A.b() → 写出A; gulp--数据流:读取A → A.a() → A.b() → 写出A. Part① 构建gu ...

  9. AngularJS 路由:ui-router

    UI-Router是Angular-UI提供的客户端路由框架,它解决了原生的ng-route的很多不足:视图不能嵌套.这意味着$scope会发生不必要的重新载入.这也是我们在Onboard中引入ui- ...

  10. Android中解析XML的方法

    假设我要解析如下的XML文件: <?xml version="1.0" encoding="UTF-8"?> <books> <b ...