【iOS】多线程1--NSThread

1、简介:

1.1 iOS有三种多线程编程的技术,分别是:

1.、NSThread

2、Cocoa NSOperationiOS多线程编程之NSOperation和NSOperationQueue的使用

3、GCD全称:Grand Central Dispatch(iOS多线程编程之Grand Central Dispatch(GCD)介绍和使用

这三种编程方式从上到下,抽象度层次是从低到高的,抽象度越高的使用越简单,也是Apple最推荐使用的。

这篇我们主要介绍和使用NSThread,后面会继续2、3 的讲解和使用。

1.2 三种方式的有缺点介绍:

NSThread:

优点:NSThread 比其他两个轻量级

缺点:需要自己管理线程的生命周期,线程同步。线程同步对数据的加锁会有一定的系统开销

NSThread实现的技术有下面三种:

Technology

Description

Cocoa threads

Cocoa implements threads using theNSThreadclass. Cocoa also provides methods onNSObjectfor spawning new threads and executing code on already-running threads. For more information, see“Using NSThread”and“Using NSObject to Spawn a Thread.”

POSIX threads

POSIX threads provide a C-based interface for creating threads. If you are not writing a Cocoa application, this is the best choice for creating threads. The POSIX interface is relatively simple to use and offers ample flexibility for configuring your threads. For more information, see“Using POSIX Threads”

Multiprocessing Services

Multiprocessing Services is a legacy C-based interface used by applications transitioning from older versions of Mac OS. This technology is available in OS X only and should be avoided for any new development. Instead, you should use theNSThreadclass or POSIX threads. If you need more information on this technology, seeMultiprocessing Services Programming Guide.

一般使用cocoa thread 技术。

Cocoa operation

优点:不需要关心线程管理,数据同步的事情,可以把精力放在自己需要执行的操作上。

Cocoa operation 相关的类是 NSOperation ,NSOperationQueue。NSOperation是个抽象类,使用它必须用它的子类,可以实现它或者使用它定义好的两个子类:NSInvocationOperation 和 NSBlockOperation。创建NSOperation子类的对象,把对象添加到NSOperationQueue队列里执行。

GCD

Grand Central Dispatch (GCD)是Apple开发的一个多核编程的解决方法。在iOS4.0开始之后才能使用。GCD是一个替代诸如NSThread, NSOperationQueue, NSInvocationOperation等技术的很高效和强大的技术。现在的iOS系统都升级到6了,所以不用担心该技术不能使用。

介绍完这三种多线程编程方式,我们这篇先介绍NSThread的使用。

2、NSThread的使用

2.1 NSThread 有两种直接创建方式:

- (id)initWithTarget:(id)targetselector:(SEL)selectorobject:(id)argument

+ (void)detachNewThreadSelector:(SEL)aSelectortoTarget:(id)aTargetwithObject:(id)anArgument

第一个是实例方法,第二个是类方法

[cpp]view plaincopy

1、[NSThread detachNewThreadSelector:@selector(doSomething:) toTarget:self withObject:nil];

2、NSThread* myThread = [[NSThread alloc] initWithTarget:self

selector:@selector(doSomething:)

object:nil];

[myThread start];

2.2参数的意义:

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

target  :selector消息发送的对象

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

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

2.3 PS:不显式创建线程的方法:

用NSObject的类方法  performSelectorInBackground:withObject: 创建一个线程:

[Obj performSelectorInBackground:@selector(doSomething) withObject:nil];

2.4 下载图片的例子:

2.4.1  新建singeView app

新建项目,并在xib文件上放置一个imageView控件。按住control键拖到viewControll

er.h文件中创建imageView IBOutlet

ViewController.m中实现:

[cpp]view plaincopy

//

//  ViewController.m

//  NSThreadDemo

//

//  Created by rongfzh on 12-9-23.

//  Copyright (c) 2012年 rongfzh. All rights reserved.

//

#import "ViewController.h"

#define kURL @"http://avatar.csdn.net/2/C/D/1_totogo2010.jpg"

@interface ViewController ()

@end

@implementation ViewController

-(void)downloadImage:(NSString *) url{

NSData *data = [[NSData alloc] initWithContentsOfURL:[NSURL URLWithString:url]];

UIImage *image = [[UIImage alloc]initWithData:data];

if(image == nil){

}else{

[self performSelectorOnMainThread:@selector(updateUI:) withObject:image waitUntilDone:YES];

}

}

-(void)updateUI:(UIImage*) image{

self.imageView.image = image;

}

- (void)viewDidLoad

{

[super viewDidLoad];

//    [NSThread detachNewThreadSelector:@selector(downloadImage:) toTarget:self withObject:kURL];

NSThread *thread= [[NSThread alloc]initWithTarget:self selector:@selector(downloadImage:) object:kURL];

[threadstart];

}

- (void)didReceiveMemoryWarning

{

[super didReceiveMemoryWarning];

// Dispose of any resources that can be recreated.

}

@end

2.4.2线程间通讯

线程下载完图片后怎么通知主线程更新界面呢?

[selfperformSelectorOnMainThread:@selector(updateUI:)withObject:imagewaitUntilDone:YES];

performSelectorOnMainThread是NSObject的方法,除了可以更新主线程的数据外,还可以更新其他线程的比如:

用:performSelector:onThread:withObject:waitUntilDone:

运行下载图片:

图片下载下来了。

2.3 线程同步

我们演示一个经典的卖票的例子来讲NSThread的线程同步:

.h

[cpp]view plaincopy

#import 

@classViewController;

@interface AppDelegate : UIResponder 

{

inttickets;

intcount;

NSThread* ticketsThreadone;

NSThread* ticketsThreadtwo;

NSCondition* ticketsCondition;

NSLock *theLock;

}

@property (strong, nonatomic) UIWindow *window;

@property (strong, nonatomic) ViewController *viewController;

@end

[cpp]view plaincopy

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions

{

tickets = 100;

count = 0;

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];

self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];

// Override point for customization after application launch.

self.viewController = [[ViewController alloc] initWithNibName:@"ViewController"bundle:nil];

self.window.rootViewController = self.viewController;

[self.window makeKeyAndVisible];

returnYES;

}

- (void)run{

while(TRUE) {

// 上锁

//        [ticketsCondition lock];

[theLock lock];

if(tickets >= 0){

[NSThread sleepForTimeInterval:0.09];

count = 100 - tickets;

NSLog(@"当前票数是:%d,售出:%d,线程名:%@",tickets,count,[[NSThread currentThread] name]);

tickets--;

}else{

break;

}

[theLock unlock];

//        [ticketsCondition unlock];

}

}

如果没有线程同步的lock,卖票数可能是-1.加上lock之后线程同步保证了数据的正确性。

上面例子我使用了两种锁,一种NSCondition ,一种是:NSLock。 NSCondition我已经注释了。

线程的顺序执行

他们都可以通过

[ticketsConditionsignal]; 发送信号的方式,在一个线程唤醒另外一个线程的等待。

比如:

[cpp]view plaincopy

#import "AppDelegate.h"

#import "ViewController.h"

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions

{

tickets = 100;

count = 0;

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];

NSThread *ticketsThreadthree = [[NSThread alloc] initWithTarget:self selector:@selector(run3) object:nil];

[ticketsThreadthree setName:@"Thread-3"];

[ticketsThreadthree start];

self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];

// Override point for customization after application launch.

self.viewController = [[ViewController alloc] initWithNibName:@"ViewController"bundle:nil];

self.window.rootViewController = self.viewController;

[self.window makeKeyAndVisible];

returnYES;

}

-(void)run3{

while(YES) {

[ticketsCondition lock];

[NSThread sleepForTimeInterval:3];

[ticketsCondition signal];

[ticketsCondition unlock];

}

}

- (void)run{

while(TRUE) {

// 上锁

[ticketsCondition lock];

[ticketsCondition wait];

[theLock lock];

if(tickets >= 0){

[NSThread sleepForTimeInterval:0.09];

count = 100 - tickets;

NSLog(@"当前票数是:%d,售出:%d,线程名:%@",tickets,count,[[NSThread currentThread] name]);

tickets--;

}else{

break;

}

[theLock unlock];

[ticketsCondition unlock];

}

}

wait是等待,我加了一个 线程3 去唤醒其他两个线程锁中的wait

其他同步

我们可以使用指令 @synchronized 来简化 NSLock的使用,这样我们就不必显示编写创建NSLock,加锁并解锁相关代码。

- (void)doSomeThing:(id)anObj

{

@synchronized(anObj)

{

// Everything between the braces is protected by the @synchronized directive.

}

}

还有其他的一些锁对象,比如:循环锁NSRecursiveLock,条件锁NSConditionLock,分布式锁NSDistributedLock等等,可以自己看官方文档学习

NSThread下载图片的例子代码:http://download.csdn.net/detail/totogo2010/4591149

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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,133评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,682评论 3 390
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,784评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,508评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,603评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,607评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,604评论 3 415
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,359评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,805评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,121评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,280评论 1 344
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,959评论 5 339
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,588评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,206评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,442评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,193评论 2 367
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,144评论 2 352

推荐阅读更多精彩内容

  • 1、简介:1.1 iOS有三种多线程编程的技术,分别是:1.、NSThread2、Cocoa NSOperatio...
    LuckTime阅读 1,343评论 0 1
  • 原文出处:容芳志的博客 简介 iOS有三种多线程编程的技术,分别是: (一)NSThread (二)Cocoa N...
    sky_kYU阅读 605评论 0 1
  • 原文出处:容芳志的博客 简介 iOS有三种多线程编程的技术,分别是: (一)NSThread(二)Cocoa NS...
    Asserts阅读 445评论 0 0
  • 一、多线程基础 基本概念 进程进程是指在系统中正在运行的一个应用程序每个进程之间是独立的,每个进程均运行在其专用且...
    AlanGe阅读 546评论 0 0
  • 人们总说大学是美好的,到了大学就到了天堂。父母说好好学习,老师说,再刻苦些…… 时光荏苒,我已到了大学,可是我...
    夏日的花香阅读 159评论 1 2