多线程这个概念的接触是蛮早的时候了,当时还是单核单CPU的时候,Thread这个概念已经出现了,当时比较流行的方案是时间片轮流,线程可以优先级抢占,但一次只能运行一个线程,实际上多线程是不能真正并行处理的,只是宏观上表现的多线程在齐头并进。现在硬件进步了很多,多核的CPU时代来临了,于是线程开始了真正意义上的并行处理,多线程也作为越来越重要的一个部分需要掌握。

iOS中关于线程的创建和运行,提供了3种方法:NSThread,NSOperation和GCD。这三种方式抽象程度越来越高,所以编写代码是越来越简单的。

我们先来看NSThread吧。

NSThread比其他两个都要更轻量级,但需要自己来管理线程的生命周期和同步,代码的编写上比其他两个复杂。对于线程的技术,苹果的官方文档上给出了一张表:

 

Technology

Description

Cocoa threads

Cocoa implements threads using the NSThread class. Cocoa also provides methods onNSObject for 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 the NSThread class or POSIX threads. If you need more information on this technology, see Multiprocessing Services Programming Guide.

苹果虽然支持3种技术,但我们实际中最常用的也就是第一种,使用NSThread来进行线程的控制。NSThread有2种初始化方式,一种是传统的init方式(initWithTarget:selector:object:),另一种是类方法(+ detachNewThreadSelector:toTarget:withObject:)

initWithTarget方法用法如下:

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

这个里面的@selector就是线程的入口点,只能接受一个传入参数,并且没有返回值。还有一个需要强调一下,init仅仅是创建了线程,要线程运行还需要调用start方法。

如果要换成detachNewThreadSelector的类方法,用法如下:

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

我们可以看到参数很像,但线程会立即运行,不需要手动调用start方法。

我们还是看代码吧,这个代码很简单,是实现后台下载,并在一张UIImage上显示。

用NSThread的方法,采用initWithTarget的做法:

#import "ViewController.h"

#define IMAGE_URL @"http://williamzhang-public.qiniudn.com/DSC_0069.jpg"

@interface ViewController ()

@end

@implementation ViewController
@synthesize imageView; - (void)downloadImage:(NSString*)url
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSData *data = [[NSData alloc] initWithContentsOfURL:[NSURL URLWithString:url]];
UIImage *image = [[UIImage alloc] initWithData:data]; if (image) {
[self performSelectorOnMainThread:@selector(updateUI:) withObject:image waitUntilDone:YES];
}
[pool drain];
} - (void)updateUI:(UIImage*)image
{
self.imageView.image = image;
} - (void)viewDidLoad
{
[super viewDidLoad]; NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(downloadImage:) object:IMAGE_URL];
[thread start]; } - (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
} - (void)dealloc {
[imageView release];
[super dealloc];
}
@end

在viewDidLoad中,我们生成一个线程并运行,线程的入口点就是downloadImage:方法,用来下载图片,并通知主线程刷新界面。
        如果采用detachNewThreadSelector方法就是把viewDidLoad方法稍微改改就行:

- (void)viewDidLoad
{
[super viewDidLoad]; [NSThread detachNewThreadSelector:@selector(downloadImage:) toTarget:self withObject:IMAGE_URL];
}

我们在开发中始终需要记住main thread是不能运行长时间没有响应的任务的,上面的例子就是一个很典型的多线程应用,但是苹果还是提供了一种更近简单的方式帮助我们简化开发的麻烦。

这就是NSObject类提供的performSelectorInBackground:withObject:方法和performSelectorOnMainThread:withObject:waitUntilDone:方法。

在上面的例子中已经使用了performSelectorOnMainThread:withObject:waitUntilDone:方法,在下载图片后就是用这个方法让主线程刷新UI的。

- (void)viewDidLoad
{
[super viewDidLoad]; [self performSelectorInBackground:@selector(downloadImage:) withObject:IMAGE_URL];
}

如果这样写的话,虽然也是本质还是多线程,但你根本感觉不到NSThread的存在,可以简单的理解就运行一个后台的任务,在不少场合还是更简单清晰一些。

最后要说的一个是生成的线程,对内存的管理也是要自己负责的,所以需要生成autorelease pool,如果你开启了ARC功能,那么可以简单的用@autoreleasepool这个关键字。

iOS多线程系列(1)的更多相关文章

  1. iOS多线程系列(3)

    在2011的WWDC上,苹果推出了GCD,从此多线程增加了一种新的方法.GCD要求运行在iOS4.0版本以上或者OS X10.6版本以上.GCD是Grand Central Dispatch的缩写,是 ...

  2. iOS多线程系列(2)

    前面了iOS的NSThread方法来实现多线程,这篇就简单的讲讲NSOperation和NSOperationQueue. NSOperation是一个抽象类,定义一个要执行的任务.NSOperati ...

  3. iOS开发系列--数据存取

    概览 在iOS开发中数据存储的方式可以归纳为两类:一类是存储为文件,另一类是存储到数据库.例如前面IOS开发系列-Objective-C之Foundation框架的文章中提到归档.plist文件存储, ...

  4. iOS开发系列--网络开发

    概览 大部分应用程序都或多或少会牵扯到网络开发,例如说新浪微博.微信等,这些应用本身可能采用iOS开发,但是所有的数据支撑都是基于后台网络服务器的.如今,网络编程越来越普遍,孤立的应用通常是没有生命力 ...

  5. iOS开发系列--并行开发其实很容易

    --多线程开发 概览 大家都知道,在开发过程中应该尽可能减少用户等待时间,让程序尽可能快的完成运算.可是无论是哪种语言开发的程序最终往往转换成汇编语言进而解释成机器码来执行.但是机器码是按顺序执行的, ...

  6. 【转】iOS开发系列--数据存取

    原文: http://www.cnblogs.com/kenshincui/p/4077833.html#SQLite 概览 在iOS开发中数据存储的方式可以归纳为两类:一类是存储为文件,另一类是存储 ...

  7. iOS多线程开发之离不开的GCD(上篇)

    一.GCD基本概念 GCD 全称Grand Central Dispatch(大中枢队列调度),是一套低层API,提供了⼀种新的方法来进⾏并发程序编写.从基本功能上讲,GCD有点像NSOperatio ...

  8. iOS开发系列

    因为最近面试了一些人,校招.初中级.高级.架构师,各种级别的,发现大家水平差异很大,有的高级的工程师很多问题都回答不上来,所以想梳理下iOS的知识点,写成一个系列,如果时间允许的话,会录制成视频放到网 ...

  9. iOS 多线程:『RunLoop』详尽总结

    1. RunLoop 简介 1.1 什么是 RunLoop? 可以理解为字面意思:Run 表示运行,Loop 表示循环.结合在一起就是运行的循环的意思.哈哈,我更愿意翻译为『跑圈』.直观理解就像是不停 ...

随机推荐

  1. centos出现磁盘坏掉,怎么修复和检测。

    当dmesg的时候,出现下面的信息说明磁盘有问题 Info fld=0x139066d0 end_request: I/O error, dev sda, sector 328230608 Buffe ...

  2. Oracle误删表空间文件后数据库无法启动

    [问题描述]Oracle误删表空间文件后数据库无法启动,报错表空间文件不存在 [解决办法]sqlplus / as sysdba       #以dba身份登陆数据库shutdown immediat ...

  3. 安全运维之:Linux系统账户和登录安全(转)

    三.删减系统登录欢迎信息 系统的一些欢迎信息或版本信息,虽然能给系统管理者带来一定的方便,但是这些信息有时候可能被黑客利用,成为攻击服务器的帮凶,为了保证系统的安全,可以修改或删除某些系统文件,需要修 ...

  4. Go语言语法汇总

    最近看了看GoLang,把Go语言的语法总结了一下,做个快速参考 数据类型 var varName type,var var1,var2… type,var varName type = Value, ...

  5. Sublime Text 3 Build 3047 32bit/64bit 简体中文安装破解版

    Sublime Text 3 Build 3047 32bit/64bit 简体中文安装破解版 Sublime Text 3 Build 3047 32bit 简体中文安装破解版下载:http://y ...

  6. javascript第十四课,方法的扩展prototype

    所谓扩展方法就是,在原函数的基础上我们往对象里面添加一些自己需要的方法,例如: string对象 string.prototype.checkEmail=function(){ //方法体 //在这里 ...

  7. poj2392 Space Elevator(多重背包)

    http://poj.org/problem?id=2392 题意: 有一群牛要上太空.他们计划建一个太空梯-----用一些石头垒.他们有K种不同类型的石头,每一种石头的高度为h_i,数量为c_i,并 ...

  8. 【main()的参数探究】

    恩...今天研究信安的课件的时候看到一段对于main(int argc,char *argv[])的编程 所以探究探究main()函数的参数 探究程序如下: #include <cstdio&g ...

  9. java 命令行制定logback参数

    -Dlogback.configurationFile=file:///export/Workspace/apache-cassandra/apache-cassandra-main/target/b ...

  10. C# 用模板生成静态页

    最近在研究静态页输出的问题,找了一些资料.做了一个简单的模板模式的静态输出 模板代码: <html xmlns="http://www.w3.org/1999/xhtml"& ...