您的位置:首页 > 移动开发 > IOS开发

ios中4种开启新的线程的处理方式以及运用范围(多线程)

2015-02-28 16:45 417 查看
一、什么是多线程

1. 每一个进程都是一个应用程序,都有独立的内存空间,一般来说一个应用程序存在一个进程,但也有多个进程的情况。

2. 同一个进程中的线程共享内存中内存和资源。

3. 线程处理方式通过堆栈的形式来处理的,先进后出。放在堆内存里面管理

4. 每一个程序如果要运行,它都会创建一个主线程(每个程序都有一个主线程),程序启动时创建(调用main来启动)。

5. 每一个程序只有一个进程,但是在一个进程里面有多个线程。(也有1个线程的情况),进程相当于是一个容器,在这个容器里面装了多个进程,线程是在运行的,它可以去调用函数调用代码。

6. 主线程的生命周期和应用程序绑定的,程序退出(结束)时,主线程也就停止了。

7. 多线程技术表示,一个应用程序有多个线程,使用多线程能够提供CPU的使用率,防止主线程堵塞。

8. 任何有可能堵塞主线程的任务不要在主线程执行(访问网络)

9. 进入后台时,主线程就会被挂起(程序退出时,主线程会被退出)

10. 每个线程相当于是一个路径,多线程相当于是多个分支的路径,由主路径(主线程)分支出来

11. 4和CPU就是多线程任务同时处理的

二、使用多线程的目的是什么

1. 引入多线程的主要目的是对大量任务进行有序的管理。通过多个任务的混合使用,可以更有效地利用计算机资源,避免主线程阻塞。

2. 比如在加载网络图片的时候,如果加载网络图片的过程用主线程来加载就会导致主线程堵塞,因为图片正在加载过程中正在使用主线程,这个时候无法操作其他了,所以这个时候可以让加载图片的操作让子线程去异步加载。

三、ios中有哪几种多线程方式

1. NSObject中的performSelectorInBackground方法

//通过NSObject的performSelectorInBackground多线程方法来异步请求图片,此方法最为简单。downLoadImage是后台(子线程)执行的方法
[self performSelectorInBackground:@selector(downLoadImage) withObject:nil];


2. NSThread

// 优点:在所有的多线程实现方式中最轻量级,可以按照需求任意控制thread对象 即:线程的加锁等操作
// 缺点:控制太繁琐 不能自己控制线程安全
// NSThread 的一个对象 就代表一个线程
NSThread *thread = [[NSThread alloc]initWithTarget:selfselector:@selector(btnUpClicked:)object:nil];
[thread start];


3. NSOperationQueue

// 优点:能够自己管理 线程安全 能够合理的安排线程 降低系统的开销 提高对线程的利用率
// 缺点:可读性差 写起来比较繁琐

NSOperationQueue *queue = [[NSOperationQueue alloc]init];
// 设置最大并发数
[queue setMaxConcurrentOperationCount:2];
NSInvocationOperation *op = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(downLoadImage) object:nil];
[queue addOperation:op];


4. GCD(比较常用,多核CPU的情况下建议使用此方式)

4.1 一般用法

// GCD 是基于队列的 多线程实现方式
// 队列的类型
// 1.并行: 多个任务同时执行 Concurrent
// 2.串行: 依次执行任务(同一事件只执行一个任务) Serial

// 自己创建一个队列
// 参数1:给队列起个名字
// 参数2:选择队列的类型 DISPATCH_QUEUE_CONCURRENT(串行)
dispatch_queue_t queue = dispatch_queue_create("test", DISPATCH_QUEUE_CONCURRENT);
// 使用队列
// 参数1: 在哪个队列执行代码
// 参数2: 要执行的代码
dispatch_async(queue, ^{
[self downLoadImage];  //回调
});


4.2 高级用法

// 系统定义了5个队列
// 1. 一个串行队列  主队列作用 : 管理主线程的相关事务

// 获得主队列
dispatch_queue_t mainQueue = dispatch_get_main_queue();
// 在主队列执行任务
//    dispatch_async(mainQueue, ^{
//        [self btnUpClicked:nil];
//    });

// 2. 4个并行队列 (并行队列)
// 参数1: 选择队列的优先级
// 参数2: 给未来使用 一般填0
dispatch_queue_t globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
//    dispatch_async(globalQueue, ^{
//        [self btnUpClicked:nil];
//    });

// 高端使用
// 1.全局队列获取数据 回到主队列将数据加载到视图上
//    dispatch_async(globalQueue, ^{
//
//        // 全局队列(子线程)获取数据
//        NSString *str = @"htt://www.baidu.com";
//        NSURL *url = [NSURL URLWithString:str];
//
//        NSData *data = [NSData dataWithContentsOfURL:url];
//        UIImage *image = [UIImage imageWithData:data];
//
//        // 返回主线程 加载UI/更新UI
//        dispatch_async(mainQueue, ^{
//
//            UIImageView *imageView = [[UIImageView alloc] init];
//            // 给视图赋值
//            imageView.image = image;
//
//        });
//    });

// 2.一段代码只执行依次
// 大部分的时候 都在单例方法中使用
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
NSLog(@"只执行依次");
});

// 3.一段代码执行多次 (全局队列有效)
// 参数1: 执行多少次
// 参数2: 在哪个队列有效
// 参数3: 要执行的内容
dispatch_apply(4, globalQueue, ^(size_t a) {
NSLog(@"%zu", a);
});

// 4.定时
// 参数1: 间隔几秒
// 参数2: 执行的内容
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(4 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
NSLog(@"=====");
});


dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
dispatch_async(dispatch_get_main_queue(), ^{
[self setImageURL];
});
});


四、代码示例

//加载网络图片时候的例子

- (void)loadImageQueueInit
{
//*****************1. 通过队列多线程来异步加载图片*****************
/*
NSOperationQueue *queue = [[NSOperationQueue alloc]init];
NSInvocationOperation *op = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(downLoadImage) object:nil];
[queue addOperation:op];
*/

//**********2. 通过NSObject的performSelectorInBackground多线程方法来异步请求图片**********//
//[self performSelectorInBackground:@selector(downLoadImage) withObject:nil];

//***************3. 通过GCD的方式创建一个新的线程来异步加载图片***************//
dispatch_queue_t queue = dispatch_queue_create("test", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(queue, ^{
[self downLoadImage];  //回调
});
}

- (void)downLoadImage
{
NSURL  *imageURL = [NSURL URLWithString:self.figureurl];
imageData = [NSData dataWithContentsOfURL:imageURL];
[_pathCover setAvatarImage:[UIImage imageWithData:imageData]];
}


让某个方法延时执行

double delayInSeconds = 10;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC);
dispatch_after(popTime, dispatch_get_main_queue(), ^{
[self setImageURL];
});
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐