iOS多线程的基本使用
一、NSThread:
程序就是一段代码,是静态的概念
进程是运行起来的程序,是动态的概念,进程需要占内存空间
线程是进程的基本单位,一个进程至少有一个线程,iOS程序默认有一个主线程,用来显示和操作UI,主线程由系统自动创建,有系统管理。如果主线程不能满足我们的需求,可以手动创建线程,手动创建的线程需要我们自己管理。
1.例:让一个线程延迟10秒运行
- (void)viewDidLoad {
[superviewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
//按钮一
UIButton *btn1 = [MyUtilcreateBtnFrame:CGRectMake(100,100, 80,40) title:@"按钮一"bgImageName:niltarget:selfaction:@selector(clickBtnOne:)];
[self.viewaddSubview:btn1];
//按钮二
UIButton *btn2 = [MyUtilcreateBtnFrame:CGRectMake(100,200, 80,40) title:@"按钮二"bgImageName:niltarget:selfaction:@selector(clickBtnTwo:)];
[self.viewaddSubview:btn2];
}
- (void)clickBtnOne:(id)sender
{
//模拟耗时较长的操作
//例如实际中的网络请求或者数据库的操作
//让线程睡眠十秒
[NSThreadsleepForTimeInterval:10];
//如果不使用多线程,会有界面假死的现象
//用户体验不好
//所有在这种情况下我们需要使用多线程
}
- (void)clickBtnTwo:(id)sender
{
NSLog(@"%s",__func__);
}
2.线程的优先级:
//用线程的这个属性来修改线程的优先级,属性值越大,执行的次数越多
t1.threadPriority =0;
- (void)viewDidLoad {
[superviewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
//线程一
NSThread *t1 = [[NSThreadalloc] initWithTarget:selfselector:@selector(threadOne)object:nil];
//修改优先级
//优先级的值在0-1之间,优先级越高,执行的次数相对来说会越多
t1.threadPriority =0;
[t1 start];
//线程二
NSThread *t2 = [[NSThreadalloc] initWithTarget:selfselector:@selector(threadTwo)object:nil];
//修改优先级,线和二大于线程一,线程二先执行完成
t2.threadPriority =1;
[t2 start];
}
- (void)threadOne
{
for (int i=0; i<100; i++) {
NSLog(@"线程一:%d", i);
}
}
- (void)threadTwo
{
for (int i=0; i<100; i++) {
NSLog(@"线程二:%d", i);
}
}
3. 线程锁:
第一种方法用: @synchronized加线程锁
-(void)withDraw:(float)money
{
//多个线程修改同一块资源的时候,会出现问题
//我们需要用线程锁的方式解决
@synchronized(self){
if (_money >= money) {
//模拟取钱的时间
[NSThreadsleepForTimeInterval:1];
_money -= money;
NSLog(@"%@取了%f元",[NSThreadcurrentThread].name,money);
}else{
NSLog(@"余额不足");
}
}
}
@end
第二种方法:
用NSLock 来实现加锁和解锁
@implementation MyAccount
{
//线程锁
NSLock *_myLock;
}
-(instancetype)init
{
if (self = [superinit]) {
_myLock = [[NSLockalloc] init];
}
returnself;
}
-(void)withDraw:(float)money
{
//多个线程修改同一块资源的时候,会出现问题
//我们需要用线程锁的方式解决
//加锁
[_myLocklock];
if (_money >= money) {
//模拟取钱的时间
[NSThreadsleepForTimeInterval:1];
_money -= money;
NSLog(@"%@取了%f元",[NSThreadcurrentThread].name,money);
}else{
NSLog(@"余额不足");
}
//解锁
[_myLockunlock];
}
@end
二:NSOpreation:
1.用NSOpreation实现在线下载图片
#import "ViewController.h"
#import "ImageOperation.h"
@interfaceViewController ()
{
NSOperationQueue *_queue;
}
@end
@implementation ViewController
- (void)viewDidLoad {
[superviewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
//创建图片视图
UIImageView *myImageView = [[UIImageViewalloc] initWithFrame:CGRectMake(40,100, 300,300)];
[self.viewaddSubview:myImageView];
//使用NSOperatio自定制类型实现多线程
//1.创建一个队列
_queue = [[NSOperationQueuealloc] init];
//队列里面同时执行的线程最大数量
//例如往队列里面加了20个线程,只会执行10个,其他的线程要等这10个中的某个执行完成之后,才能执行
_queue.maxConcurrentOperationCount =10;
//2.创建ImageOperation对象
ImageOperation *op = [[ImageOperationalloc] init];
//设置下载链接
op.urlString=@"http://g.hiphotos.baidu.com/image/pic/item/4034970a304e251fb3145e6ca586c9177e3e5346.jpg";
//设置显示的视图
op.imgView = myImageView;
//添加到队列
[_queueaddOperation:op];
//ASIHttpRequest: NSOperation
}
////////////////////////////////////////////////////////////////////////////////////////////////////////
#import "ImageOperation.h"
@implementation ImageOperation
//使用NSOperation自定制对象创建线程时的执行体
-(void)main
{
//下载图片
NSURL *url = [NSURLURLWithString:self.urlString];
NSData *data = [NSDatadataWithContentsOfURL:url];
//回到主线程修改UI
[selfperformSelectorOnMainThread:@selector(refreshUI:)withObject:data waitUntilDone:YES];
}
- (void)refreshUI:(NSData *)data
{
self.imgView.image = [UIImageimageWithData:data];
}
@end
2.使用NSOperation创建多线程:
- (void)viewDidLoad {
[superviewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
//NSOperation实现多线程
//1.创建队列
_queue = [[NSOperationQueuealloc] init];
//2.创建NSInvocationOperation对象
/*
第一个参数:线程执行体方法所属的对象
第二个参数:线程执行体方法
第三个参数:线程执行体方法传递的实参
*/
NSInvocationOperation *op1 = [[NSInvocationOperationalloc]initWithTarget:selfselector:@selector(threadOne)object:nil];
//线程结束之后执行的代码块
[op1 setCompletionBlock:^{
NSLog(@"线程一结束");
}];
//3.开启线程
[_queueaddOperation:op1];
//第二种实现线程的方式
NSBlockOperation *op2 = [NSBlockOperationblockOperationWithBlock:^{
//线程的执行体
for (int i=0; i<100; i++) {
NSLog(@"执行线程二:%d",i);
}
}];
//线程执行结束后调用的代码块
[op2 setCompletionBlock:^{
NSLog(@"线程二结束");
}];
//添加到队列里面
[_queueaddOperation:op2];
}
//线程执行体方法
- (void)threadOne
{
for (int i=0; i<100; i++) {
NSLog(@"执行了线程一:%d", i);
}
}
三:GCD:
1.用GCD实现多线程:
#import "ViewController.h"
@interfaceViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[superviewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
//1.同一块代码执行多次
//[self testApply];
//2.代码只执行一次
// [self testOnce];
// [self testOnce];
// [self testOnce];
// [self testOnce];
//3.在一段时间之后执行代码块
//[self testAfter];
//4.线程组(group)
//[self testGroup];
//5.在某几个线程都执行完成之后,并在另外几个线程都执行完成之前,需要执行一些代码
[selftestBarrier];
}
//5.在某几个线程都执行完成之后,并在另外几个线程都执行完成之前,需要执行一些代码
- (void)testBarrier
{
//队列不能是系统的全局队列
dispatch_queue_t concurrentQueue =dispatch_queue_create("concurrentQueue",DISPATCH_QUEUE_CONCURRENT);
//线程一
dispatch_async(concurrentQueue, ^{
for (int i=0; i<100; i++) {
NSLog(@"线程一:%d", i);
}
});
//线程二
dispatch_async(concurrentQueue, ^{
for (int i=0; i<100; i++) {
NSLog(@"线程二:%d", i);
}
});
//在线程一和线程二都执行完成之后,并且在线程三执行之前,调用一段代码块
dispatch_barrier_async(concurrentQueue, ^{
NSLog(@"barrier");
});
//线程三
dispatch_async(concurrentQueue, ^{
for (int i=0; i<100; i++) {
NSLog(@"线程三:%d", i);
}
});
}
//4.多个线程都执行之后去执行一些代码
- (void)testGroup
{
//线程组
dispatch_group_t group =dispatch_group_create();
/*
第一个参数:线程组
第二个参数:线程所在的队列
第三个参数:线程的执行体
*/
dispatch_group_async(group,dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0), ^{
for (int i=0; i<100; i++) {
NSLog(@"执行了线程一:%d", i);
}
});
dispatch_group_async(group,dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0), ^{
for (int i=0; i<100; i++) {
NSLog(@"执行了线程二:%d", i);
}
});
//在该组的所有线程都执行结束时做执行某段代码
dispatch_group_notify(group,dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0), ^{
NSLog(@"所有线程都执行完成");
});
}
//3.在一段时间之后执行代码块
- (void)testAfter
{
NSLog(@"执行之前");
//DISPATCH_TIME_NOW:表示当前的时间
//当前时间的十秒之后
dispatch_time_t myTime =dispatch_time(DISPATCH_TIME_NOW,NSEC_PER_SEC*10);
//队列
//创建一个并行的队列
dispatch_queue_t concurrentQueue =dispatch_queue_create("concurrentQueue",DISPATCH_QUEUE_CONCURRENT);
/*
第一个参数:代码块执行的时间
第二个参数:代码块的线程所在的队列
第三个参数:执行的代码块
*/
dispatch_after(myTime, concurrentQueue, ^{
NSLog(@"执行了代码块");
});
}
//2.代码只执行一次
//通常用来实现单例
- (void)testOnce
{
staticdispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
NSLog(@"执行了一次");
});
}
//1.同一块代码执行多次
- (void)testApply
{
/*
第一个参数:代码块执行多少次
第二个参数:线程所在的队列
第三个参数:线程的执行体
*/
dispatch_queue_t globalQueue =dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0);
//参数表示当前是第几次执行
dispatch_apply(10, globalQueue, ^(size_t time) {
//线程的执行体
NSLog(@"执行到了第%ld次", time);
});
}
- (void)didReceiveMemoryWarning {
[superdidReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end
2.GCD实现多线程2:
- (void)viewDidLoad {
[superviewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
//GCD实现多线程
//一、GCD的队列
//1.主线程所在的串行队列
//系统自动创建了这个队列,我们只要获取后使用
dispatch_queue_t mainQueue =dispatch_get_main_queue();
//2.系统的全局并行队列
//系统自动创建了这个队列,我们只能获取后使用
/*
第一个参数:队列的优先级
第二个参数:APPLE公司保留的参数
*/
dispatch_queue_t globalQueue =dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0);
//3.自己创建的队列
//1)串行队列
/*
第一个参数:队列的标识符
第二个参数:用来区分是串行队列还是并行队列
DISPATCH_QUEUE_SERIAL:串行队列
DISPATCH_QUEUE_CONCURRENT:并行队列
*/
dispatch_queue_t serialQueue =dispatch_queue_create("serialQueue",DISPATCH_QUEUE_SERIAL);
//2)并行队列
dispatch_queue_t concurrentQueue =dispatch_queue_create("concurrentQueue",DISPATCH_QUEUE_CONCURRENT);
//二、GCD创建线程
//1、异步将线程的执行体代码放到队列执行
/*
第一个参数:队列
第二个参数:线程的执行体代码
*/
dispatch_queue_t queueOne =dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0);
dispatch_async(queueOne, ^{
for (int i=0; i<100; i++) {
NSLog(@"执行了线程一:%d", i);
}
});
//2、同步将线程的执行体放到队列执行
dispatch_sync(queueOne, ^{
for (int i=0; i<100; i++) {
NSLog(@"执行了线程二:%d", i);
}
});
}
- (void)didReceiveMemoryWarning {
[superdidReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end
3.GCD的串行和并行队列:
#import "ViewController.h"
@interfaceViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[superviewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
//1.以同步的方式在串行队列创建两个线程
//[self testSyncWithSerialQueue];
//2.以同步的方式在并行队列创建两个线程
//[self testSyncWithConcurrentQueue];
//3.以异步的方式在串行队列创建两个线程
//[self testAsyncWithSerialQueue];
//4.以异步的方式在并行队列创建两个线程
[selftestAsyncWithConcurrentQueue];
}
//4.以异步的方式在并行队列创建两个线程
//前面的线程和后面的线程同时执行
- (void)testAsyncWithConcurrentQueue
{
//创建并行队列
dispatch_queue_t concurrentQueue =dispatch_queue_create("concurrentQueue",DISPATCH_QUEUE_CONCURRENT);
//线程一
dispatch_async(concurrentQueue, ^{
for (int i=0; i<100; i++) {
NSLog(@"线程一:%d", i);
}
});
//线程二
dispatch_async(concurrentQueue, ^{
for (int i=0; i<100; i++) {
NSLog(@"线程二:%d", i);
}
});
}
//3.以异步的方式在串行队列创建两个线程
//前面的线程执行完成,后面的线程才开始执行
- (void)testAsyncWithSerialQueue
{
//串行队列
dispatch_queue_t serialQueue =dispatch_queue_create("myQueue",DISPATCH_QUEUE_SERIAL);
//线程一
dispatch_async(serialQueue, ^{
for (int i=0; i<100; i++) {
NSLog(@"线程一:%d", i);
}
});
//线程二
dispatch_async(serialQueue, ^{
for (int i=0; i<100; i++) {
NSLog(@"线程二:%d", i);
}
});
}
//2.以同步的方式在并行队列创建两个线程
//前面的线程执行结束,才开始执行后面的线程
- (void)testSyncWithConcurrentQueue
{
//获取全局并行队列
dispatch_queue_t globalQueue =dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0);
//线程一
dispatch_sync(globalQueue, ^{
for (int i=0; i<100; i++) {
NSLog(@"线程一:%d", i);
}
});
//线程二
dispatch_sync(globalQueue, ^{
for (int i=0; i<100; i++) {
NSLog(@"线程二:%d", i);
}
});
}
//1.以同步的方式在串行队列创建两个线程
//前面的线程执行完成之后,才开始执行后面的线程
- (void)testSyncWithSerialQueue
{
//创建一个串行队列
dispatch_queue_t serialQueue =dispatch_queue_create("serialQueue",DISPATCH_QUEUE_SERIAL);
//线程一
dispatch_sync(serialQueue, ^{
for (int i=0; i<100; i++) {
NSLog(@"线程一:%d", i);
}
});
//线程二
dispatch_sync(serialQueue, ^{
for (int i=0; i<100; i++) {
NSLog(@"线程二:%d", i);
}
});
}
iOS多线程的基本使用的更多相关文章
- iOS多线程主题
下面是:2个并发进程.和2个并发线程的示意图: 下面介绍三种多线程技术(Thread.Cocoa Operation.Grand Central Dispatch): 1.最轻量级Thread(需要自 ...
- iOS多线程技术方案
iOS多线程技术方案 目录 一.多线程简介 1.多线程的由来 2.耗时操作的模拟试验 3.进程和线程 4.多线程的概念及原理 5.多线程的优缺点和一个Tip 6.主线程 7.技术方案 二.Pthrea ...
- iOS 多线程GCD的基本使用
<iOS多线程简介>中提到:GCD中有2个核心概念:1.任务(执行什么操作)2.队列(用来存放任务) 那么多线程GCD的基本使用有哪些呢? 可以分以下多种情况: 1.异步函数 + 并发队列 ...
- iOS多线程到底不安全在哪里?
iOS多线程安全的概念在很多地方都会遇到,为什么不安全,不安全又该怎么去定义,其实是个值得深究的话题. 共享状态,多线程共同访问某个对象的property,在iOS编程里是很普遍的使用场景,我们就从P ...
- iOS多线程的详情使用示例--简进祥
大家都知道,在开发过程中应该尽可能减少用户等待时间,让程序尽可能快的完成运算.可是无论是哪种语言开发的程序最终往往转换成汇编语言进而解释成机器码来执行.但是机器码是按顺序执行的,一个复杂的多步操作只能 ...
- iOS多线程
关于iOS多线程 概述 这篇文章中,我不会说多线程是什么.线程和进程的区别.多线程有什么用,当然我也不会说什么是串行.什么是并行等问题,这些我们应该都知道的. 在 iOS 中其实目前有 4 套多线程方 ...
- iOS多线程学习及总结
能有份网上的存储资料,备以后提升及参考 iOS 多线程编程 简介 一. iOS有三种多线程编程的技术,分别是: 1. NSThread 2. Cocoa NSOp ...
- iOS多线程杂论
iOS多线程的分布 (1) NSThread (2) NSOperation (3) GCD 现在对下面三个进行一个个的分析,希望那里说得不对的地方希望简友们帮我指点一二. 1,NSThread 优点 ...
- iOS多线程开发
概览 大家都知道,在开发过程中应该尽可能减少用户等待时间,让程序尽可能快的完成运算.可是无论是哪种语言开发的程序最终往往转换成汇编语言进而解释成机器码来执行.但是机器码是按顺序执行的,一个复杂的多步操 ...
- iOS多线程编程之NSThread的使用
目录(?)[-] 简介 iOS有三种多线程编程的技术分别是 三种方式的有缺点介绍 NSThread的使用 NSThread 有两种直接创建方式 参数的意义 PS不显式创建线程的方法 下载图片的例子 ...
随机推荐
- 好用的DNS服务器推荐
DNS在平时上网中扮演重要角色,如果不注意DNS的话,可能会导致网速慢.弹窗广告.网址打不开.打开不是自己想要的网站.淘宝客劫持等一系列问题.针对DNS的问题,网络上也有各种DNS平台供用户选择.这里 ...
- URAL 1736 Chinese Hockey 网络流+建图
题目链接:点击打开链接 题意: 给定n个队伍的得分情况,输出随意一个可行解. n个队伍随意2个队伍 a, b 间有且仅有一场比赛. 比赛结果分4种: 1.a +3, b +0 2.a +0, b +3 ...
- ASP.NET打印EXCEl报表技术总结
序言:我们在做企业项目或者一些管理系统的时候往往会用到导出到excel报表这项功能,下面我介绍的是用windows自带的excel来打印 首先必须引入:Interop.Excel.dll.Intero ...
- L10 数据入站、转发、出站流程
二 写出防火墙规则链之间的顺序也就是入站数据流向.转发数据流向.出站数据流向的过程 入站:PREROUTING→INPUT 数据包到达防火墙,由prerouting处理,判断是否修改地址 路由选择:判 ...
- 5.7.13mysql 无法登陆
话不多说 用的http://dev.mysql.com/downloads/mysql/下的ZIP Archive安装方式 下载 解压,然后吧bin目录添加到系统path环境变量下.然后将my-de ...
- 反编译C#的dll文件并修改,再重新生成dll
1.把dll文件导入到ildasm工具中,ildasm是由微软提供的.net程序反编译工具,位于“C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A ...
- C# 对XML基本操作总结
C# 对XML基本操作包括读取节点的数据,添加节点.读取节点属性,修改节点属性等.具体如下: XML文件:文件在MyDocument文件夹下 <?xml version="1.0&qu ...
- java之集合类特性对比分析列表
类集合框架有很多文章都列出了继承关系图,但是我没有找到更清晰的特性对比图,我这里根据使用选择条件总结对比罗列一下它们之间的一些特点.
- winform制作自定义控件(入门)
原文链接:http://blog.csdn.net/bychentufeiyang/article/details/7081402 与原文基本一致,只是例子变成VS2012环境,语言采用博主常用的 ...
- 安装程序时出现错误代码0x80070422
通过win10应用商店,下载应用,安装时出现错误代码0x80070422. 需要打开services.msc,将windows update服务打开.