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不显式创建线程的方法 下载图片的例子 ...
随机推荐
- hdu 2660 Accepted Necklace(dfs)
Problem Description I have N precious stones, and plan to use K of them to make a necklace for my mo ...
- ASP.NET获取IP的6种方法 【转】
).ToString();//方法四(无视代理)HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR" ...
- docker学习笔记(1)
(1)Docker介绍 关于Docker的介绍,我就不列举出来了.到百度.谷歌搜索.非常多介绍文章.以下我给出官网的介绍:https://www.docker.com/whatisdocker/ (2 ...
- 使用工具来提升Android开发效率
正所谓工欲善其事,必先利其器.学习并应用优秀的轮子,能够让我们跑的更快,走的更远.这里所指的工具是广义的,泛指能帮助我们开发的东西,或者能提高我们效率的东西,包含:开发工具.监測工具.第三方代码库等. ...
- XML是什么,它能够做什么?——写给XML入门者
XML就可以扩展标记语言(eXtensible Markup Language).标记是指计算机所能理解的信息符号,通过此种标记,计算机之间能够处理包括各种信息的文章等.怎样定义这些标记,既能够选择国 ...
- 图的邻接表存储 c实现
图的邻接表存储 c实现 (转载) 用到的数据结构是 一个是顶点表,包括顶点和指向下一个邻接点的指针 一个是边表, 数据结构跟顶点不同,存储的是顶点的序号,和指向下一个的指针 刚开始的时候把顶点表初始化 ...
- Windows 2012 AD配置
//本文选在快帮网,非原创. Active Directory概述: 使用 Active Directory(R) 域服务 (AD DS) 服务器角色,可以创建用于用户和资源管理的可伸缩.安全及可管理 ...
- Mvc4.0添加商品到Cookie
/// <summary> /// 添加Cookie /// </summary> /// <param name="gc">GoodsToCo ...
- Android 打开系统最近任务及最近应用方法
Class serviceManagerClass; try { serviceManagerClass = Class.forName("android.os.ServiceManager ...
- ASP.NET版本的Kindeditor插件的使用
1.先从官网中现在最新版本的Kindeditor,官网地址:http://www.kindsoft.net/ 下载之后的目录结构如下: