iOS-多线程--介绍NSThread和GCD及其它们的线程通讯示例
前言:下面就不一一列出 pthread、NSThread、GCD、NSOperation 的完整的各种方法了,只分别将最常用的列出来,以便偶尔瞄一眼。
一、NSThread
1> 线程间的通讯
/** 这个例子为在创建的子线程中下载图片,然后回到主线程中设置图片 ( 更新UI ) */
- (void)viewDidLoad
{
[super viewDidLoad];
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
// 隐式创建并启动线程
[self performSelectorInBackground:@selector(download) withObject:nil];
}
/**
* 图片下载
*/
- (void)download
{
NSLog(@"download---%@", [NSThread currentThread]);
// 1.图片地址
NSString *urlStr = @"http://d.hiphotos.baidu.com/image/pic/item/37d3d539b6003af3290eaf5d362ac65c1038b652.jpg";
NSURL *url = [NSURL URLWithString:urlStr];
// 2.根据地址下载图片的二进制数据(耗时的代码)
NSLog(@"---begin");
NSData *data = [NSData dataWithContentsOfURL:url];
NSLog(@"---end");
// 3.设置图片
UIImage *image = [UIImage imageWithData:data];
// 4.回到主线程,刷新UI界面(为了线程安全)
[self performSelectorOnMainThread:@selector(downloadFinished:) withObject:image waitUntilDone:NO];
// [self performSelector:@selector(downloadFinished:) onThread:[NSThread mainThread] withObject:image waitUntilDone:YES];
// [self.imageView performSelectorOnMainThread:@selector(setImage:) withObject:image waitUntilDone:YES];
NSLog(@"-----over----");
}
- (void)downloadFinished:(UIImage *)image
{
self.imageView.image = image;
NSLog(@"downloadFinished---%@", [NSThread currentThread]);
}
@end
/****************************分割线****************************/
二、GCD
1> 、GCD 【 (任务)同步/异步***(队列)串行/并发*****任务和队列的几种组合方式 】
- (void)viewDidLoad
{
[super viewDidLoad];
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
[self asyncSerialQueue];
}
// 就下面三个最常用,(GCD中其他情况不要管)
/**
* 第一种组合方式
* async -- 并发队列(最常用)
* 会不会创建线程:会,一般同时开多条
* 任务的执行方式:并发执行
*/
- (void)asyncGlobalQueue
{
// 获得全局的并发队列
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
// 将 任务 添加 全局队列 中去 异步 执行
dispatch_async(queue, ^{
NSLog(@"-----下载图片1---%@", [NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"-----下载图片2---%@", [NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"-----下载图片3---%@", [NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"-----下载图片4---%@", [NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"-----下载图片5---%@", [NSThread currentThread]);
});
}
/**
*第一种组合方式 打印结果
2016-04-07 17:48:05.007 Test-GCD测试一下[909:50754] -----下载图片2---<NSThread: 0x7f8acb50ea50>{number = 3, name = (null)}
2016-04-07 17:48:05.007 Test-GCD测试一下[909:50755] -----下载图片1---<NSThread: 0x7f8acb4bedf0>{number = 2, name = (null)}
2016-04-07 17:48:05.007 Test-GCD测试一下[909:50762] -----下载图片4---<NSThread: 0x7f8acb71b570>{number = 5, name = (null)}
2016-04-07 17:48:05.007 Test-GCD测试一下[909:50763] -----下载图片5---<NSThread: 0x7f8acb510160>{number = 6, name = (null)}
2016-04-07 17:48:05.007 Test-GCD测试一下[909:50758] -----下载图片3---<NSThread: 0x7f8acb60e780>{number = 4, name = (null)}
*/
/**
* 第二种组合方式
* async -- 串行队列(有时候用)
* 会不会创建线程:会,一般只开1条线程
* 任务的执行方式:串行执行(一个任务执行完毕后再执行下一个任务)
*/
- (void)asyncSerialQueue
{
// 1.创建一个串行队列
dispatch_queue_t queue = dispatch_queue_create("cn.heima.queue", NULL);
// 2.将任务添加到串行队列中 异步 执行
dispatch_async(queue, ^{
NSLog(@"-----下载图片1---%@", [NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"-----下载图片2---%@", [NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"-----下载图片3---%@", [NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"-----下载图片4---%@", [NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"-----下载图片5---%@", [NSThread currentThread]);
});
// 3.非ARC,需要释放创建的队列
// dispatch_release(queue);
}
/**
* 第二种方式 打印结果
2016-04-07 17:49:33.730 Test-GCD测试一下[921:52233] -----下载图片1---<NSThread: 0x7f926ad09e20>{number = 2, name = (null)}
2016-04-07 17:49:33.731 Test-GCD测试一下[921:52233] -----下载图片2---<NSThread: 0x7f926ad09e20>{number = 2, name = (null)}
2016-04-07 17:49:33.731 Test-GCD测试一下[921:52233] -----下载图片3---<NSThread: 0x7f926ad09e20>{number = 2, name = (null)}
2016-04-07 17:49:33.731 Test-GCD测试一下[921:52233] -----下载图片4---<NSThread: 0x7f926ad09e20>{number = 2, name = (null)}
2016-04-07 17:49:33.731 Test-GCD测试一下[921:52233] -----下载图片5---<NSThread: 0x7f926ad09e20>{number = 2, name = (null)}
*/
/**
* 第三种方式 (这是一种特殊的方式,将 任务 添加到主队列中 异步 执行)
* async -- 主队列(很常用) (一般在线程之间的通讯才用得上 @xz)
*/
- (void)asyncMainQueue
{
// 1.主队列(添加到主队列中的任务,都会自动放到主线程中去执行)
dispatch_queue_t queue = dispatch_get_main_queue();
// 2.添加 任务 到主队列中 异步 执行
dispatch_async(queue, ^{
NSLog(@"-----下载图片1---%@", [NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"-----下载图片2---%@", [NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"-----下载图片3---%@", [NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"-----下载图片4---%@", [NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"-----下载图片5---%@", [NSThread currentThread]);
});
}
/**
* 第三种方式 打印结果如下:
2016-04-07 16:50:04.245 Test-GCD测试一下[801:31778] -----下载图片1---<NSThread: 0x7fb2a2d0a1e0>{number = 1, name = main}
2016-04-07 16:50:04.246 Test-GCD测试一下[801:31778] -----下载图片2---<NSThread: 0x7fb2a2d0a1e0>{number = 1, name = main}
2016-04-07 16:50:04.246 Test-GCD测试一下[801:31778] -----下载图片3---<NSThread: 0x7fb2a2d0a1e0>{number = 1, name = main}
2016-04-07 16:50:04.247 Test-GCD测试一下[801:31778] -----下载图片4---<NSThread: 0x7fb2a2d0a1e0>{number = 1, name = main}
2016-04-07 16:50:04.248 Test-GCD测试一下[801:31778] -----下载图片5---<NSThread: 0x7fb2a2d0a1e0>{number = 1, name = main}
*/
2> GCD------线程间通讯示例
注意点:
<1>. 需要设置按钮的image和backgroundImage,建议先把按钮类型改为custom,才能保证设置成功
<2>. 属性名不能以new开头
<3>. 只有在init开头的构造方法中,才允许对self进行赋值
#define XZGlobalQueue dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)
#define XZMainQueue dispatch_get_main_queue()
#import "XZViewController.h"
@interface XZViewController ()
@property (weak, nonatomic) IBOutlet UIButton *button;
@end
@implementation XZViewController
- (void)viewDidLoad
{
[super viewDidLoad];
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(20, 20, 100, 60)];
[self.view addSubview:button];
self.button = button;
dispatch_async(XZGlobalQueue, ^{
NSLog(@"donwload---%@", [NSThread currentThread]);
// 1.子线程下载图片
NSURL *url = [NSURL URLWithString:@"http://d.hiphotos.baidu.com/image/pic/item/37d3d539b6003af3290eaf5d362ac65c1038b652.jpg"];
NSData *data = [NSData dataWithContentsOfURL:url];
UIImage *image = [UIImage imageWithData:data];
// 2.回到主线程设置图片
dispatch_async(XZMainQueue, ^{
NSLog(@"setting---%@ %@", [NSThread currentThread], image);
[self.button setImage:image forState:UIControlStateNormal];
});
});
}
@end
/*
* 打印结果
Test-GCD测试一下[873:44012] donwload---<NSThread: 0x7fc7a0401d50>{number = 2, name = (null)}
Test-GCD测试一下[873:43920] setting---<NSThread: 0x7fc7a0507930>{number = 1, name = main} <UIImage: 0x7fc7a0681530>, {440, 608}
*/
/****************************分割线****************************/
iOS-多线程--介绍NSThread和GCD及其它们的线程通讯示例的更多相关文章
- iOS多线程开发--NSThread NSOperation GCD
多线程 当用户播放音频.下载资源.进行图像处理时往往希望做这些事情的时候其他操作不会被中 断或者希望这些操作过程中更加顺畅.在单线程中一个线程只能做一件事情,一件事情处理不完另一件事就不能开始,这样势 ...
- iOS 多线程(NSThread、GCD、NSOperation)
ios中得多线程技术主要使用3种:NSThread.NSOperation和GCD 一.NSThread: 最轻量级方法,但是不安全需要手动加锁,需要自己管理生命周期 NSThread的使用方法有2种 ...
- iOS的三种多线程技术NSThread/NSOperation/GCD
1.iOS的三种多线程技术 1.NSThread 每个NSThread对象对应一个线程,量级较轻(真正的多线程) 2.以下两点是苹果专门开发的"并发"技术,使得程序员可以不再去关心 ...
- 多线程技术 NSThread & NSOperation & GCD
多线程:在iOS开发中,用到多线程的处理问题的时候有很多,比如异步下载数据时刷新界面等等. 引入多线程来处理问题的关键就是,基于多线程可以使界面更加流畅,防止界面假死. 界面假死:比如你单击一个按钮来 ...
- iOS多线程(上)——GCD详解(上)
GCD(Grand central Dispatch)是Apple开发的一个多核编程的较新的解决方法.它主要用于优化应用程序以支持多核处理器以及其他对称多处理系统.下面我讲讲述关于GCD的点,通篇读完 ...
- iOS 多线程之 NSThread的基本使用
一个NSThread对象就代表一条线程 下面是NSThread开启线程的方法 - (void)touchesBegan:(NSSet<UITouch *> *)touches withEv ...
- IOS多线程(NSThread)
1.创建方法 使用NSThread创建线程主要有两个个方法,分别如下 NSThread* myThread = [[NSThread alloc] initWithTarget:self sele ...
- iOS多线程介绍
一.线程概述 有些程序是一条直线,起点到终点:有些程序是一个圆,不断循环,直到将它切断.直线的如简单的Hello World,运行打印完,它的生命周期便结束了,像昙花一现那样:圆如操作系统,一直运行直 ...
- 多线程&NSObject&NSThread&NSOperation&GCD
1.NSThread 每个NSThread对象对应一个线程,量级较轻(真正的多线程) 以下两点是苹果专门开发的“并发”技术,使得程序员可以不再去关心线程的具体使用问题 2.NSOperation/NS ...
随机推荐
- ECMASCRIPT 6中字符串的新特性
本文将覆盖在ECMAScript 6 (ES6)中,字符串的新特性. Unicode 码位(code point)转义 Unicode字符码位的长度是21位[2].而JavaScript的字符串,是1 ...
- django 快速实现session的操作
说明: 从这一篇开始就不再完整的介绍django项目的创建过程了,因为前面几篇博客中都详细的介绍了这个创建过程,套路都是一样的,熟悉了这个套路,后面要做的是一些细节技术点的学习和练习. 上一节讲到了d ...
- 前端优化:RequireJS Optimizer 的使用和配置方法
RequireJS Optimizer 是 RequireJS 自带的前端优化工具,可以对 RequireJS 项目中的 JavaScript & CSS 代码使用 UglifyJS 或者 C ...
- Muduo 多线程模型对比
本文主要对比Muduo多线程模型方案8 和方案9 . 方案8:reactor + thread pool ,有一个线程来充当reactor 接受连接分发事件,将要处理的事件分配给thread pool ...
- Blocked Process Report
当同个对象上有互斥的锁存在时,查询需要等待很长时间,我们是否可以收到来自SQL Server提醒?答案是可以的,做法非常简单,因为SQL Server为你提供了称为Blocked Process Re ...
- 对于大于8046 bytes的行,RCSI/SI事务隔离级别无效
自SQL Server 2005起,我们有了READ COMMITTED SNAPSHOT ISOLATION level (RCSI) 和SNAPSHOT ISOLATION level (SI)两 ...
- sprint3(第三天)
今天在做的任务是整合前台和后台,使前台可以从后台得到数据 燃尽图:
- Ubuntu13.04配置:Vim+Syntastic+Vundle+YouCompleteMe
序言 使用Ubuntu和vim已经有一段时间了,对于Vim下的插件应用,我总是抱着一股狂热的态度.这次,又在网上闲逛着,发现了一个个人博客提到了Vim代码补全这回事,并提到了YouCompleteMe ...
- .Net一般处理程序来实现用户名的验证
一般处理程序 在说一般处理程序之前,先来看看什么是aspx.在vs中,使用的大多是aspx页面.aspx页面就是在接收到一个请求之后,将返回的结果生成一个html页面返回给服务器.当我们有时候需要自己 ...
- Excel大数据量分段导入到Oracle
客户需要将一个具有2W多条数据的Excel表格中的数据导入到Oracle数据库的A表中,开始采用的是利用Oledb直接将数据读入到DataTable中,然后通过拼接InserInto语句来插入到数据库 ...