实现分线程

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u010105969/article/details/48010147

实现分线程

预备概念:

1.进程:一个正在执行的程序

2.线程:由一堆不分叉的CPU指令组成的集合(一个进程中至少包含一个线程)

3.上下文切换:假设一个CPU同时负责两个线程,当线程1时间片结束以后会将线程1的相关信息保存到寄存器中。接下来将时间片分配给线程2,线程2时间片到了以后又将线程2信息保存起来。接下来唤醒线程1的寄存器,将其信息取出,接着上一次执行的命令继续执行,来回切换,直到所有的CPU命令全部完成。

4.多线程的优势和缺点:

一.缺点:

(1)每个线程都会开辟一个空间,如果大量使用多线程会占用大量内存影响性能。

(2)资源竞争。   上锁    

(3) 死锁。

二. 优点:

提高用户体验

我们现在的主要目的是实现分线程,目前了解到的有三种方式

1.利用NSObject实现分线程:

开辟一个分线程的代码:

[selfperformSelectorInBackground:@selector(getData)withObject:nil];

分线程中的代码:

- (void)getData {

NSString *path =@"http://c.hiphotos.baidu.com/image/h%3D200/sign=4652d7cac8bf6c81e8372be88c3fb1d7/ d50735fae6cd7b89448109210b2442a7d8330ea6.jpg";

NSURL *url = [NSURLURLWithString:path];

NSData *data = [NSDatadataWithContentsOfURL:url];

UIImage *image = [UIImageimageWithData:data];

    [selfperformSelectorOnMainThread:@selector(refreshUI:)withObject:image waitUntilDone:NO];

}

此分线程中的代码是获取网络上的一幅图片,这就要设计到刷新UI的问题,刷新UI只能在主线程中,当分线程下载完数据后一定要立刻返回到主线程中,否则就会有延迟。虽然不返回也能实现刷新的效果,这是因为主线程会定时访问分线程,看其是否完成了任务。

主线程刷新UI的代码:

- (void)refreshUI:(id)obj {

self.myImageView.image = obj;

}

2.利用NSThread实现分线程

开辟分线程的代码:

//   创建一个线程

NSThread *thread = [[NSThreadalloc] initWithTarget:selfselector:@selector(getData)object:nil];

//    需要手动启动线程

    [thread start];

利用NSThread这个类来创建,和其他类创建对象是一样的,至于其分线程中的代码是和NSObject中的代码一样的就不太粘贴了。

3.GCD异步下载数据:

GCD:Grand Central Dispatch

利用GCD可以创建队列,然后将任务添加到队列中,这样就产生了一个线程来完成队列中的任务,线程中所有任务结束结束后同样要返回到主线程。

代码:

dispatch_queue_t queue = dispatch_queue_create("com.qianfeng",NULL);

NSLog(@"--%@",[NSThreadcurrentThread]);

dispatch_async(queue, ^{

NSLog(@"++%@",[NSThreadcurrentThread]);

NSString *path =@"http://c.hiphotos.baidu.com/image/h%3D200/sign=4652d7cac8bf6c81e8372be88c3fb1d7/          

d50735fae6cd7b89448109210b2442a7d8330ea6.jpg";    

NSURL *url = [NSURLURLWithString:path];

NSData *data = [NSDatadataWithContentsOfURL:url];

UIImage *image = [UIImageimageWithData:data];

__weak typeof(self) weakSelf =self;

//        回到主线程

dispatch_async(dispatch_get_main_queue(), ^{

//            回到主线程刷新UI,如果不回到主线程刷新UI,刷新会有延迟

            weakSelf.myImageView.image = image;

NSLog(@"回到主线程:%@",[NSThreadcurrentThread]);

        });

    });

sleep(2);

NSLog(@"====%@",[NSThreadcurrentThread]);

创建队列中的第二个参数为空说明创建的是一个串行队列(什么是串行队列? 待会说)。代码中的几个nslog语句可以显示程序的执行顺序,并不是执行完分线程,才再去执行主线程的(我们添加分线程是为了提高速度,缩短程序运行时间,提高用户体验)。

说说串行队列:

队列可以分为串行队列和并行队列,联想一下串行电路和并行电路。当队列是串行队列的时候,队列中添加的任务是按顺序执行的,哪怕添加再多的任务也只是一个线程而已。(串行队列中的任务执行顺序只与添加的顺序有关)  与串行队列相对应的是并行队列,并行队列中任务的执行顺序是不确定的,一个并行队列中可能有多个线程,因为只要往队列中添加一个任务就会产生一个线程。

并行队列:

并行队列的创建和串行队列的创建相似,只是第二个参数有所变化。

代码:

dispatch_queue_t queue =dispatch_queue_create("com.1000phone",DISPATCH_QUEUE_CONCURRENT);

切记任务完成后返回主线程。

在并行队列中我们可以利用group来监听并行队列中的全部线程什么时候结束(并行队列中线程的执行顺序是不确定,不好判断什么时候结束,不像并行队列那样,可以在所有任务后再添加一个任务来显示串行队列中的所有任务结束)。

代码:

//    1.创建一个并行队列

dispatch_queue_t queue =dispatch_queue_create("com.1000phone",DISPATCH_QUEUE_CONCURRENT);

//    2.创建一个group

dispatch_group_t group =dispatch_group_create();

//    3.将任务添加到队列里面

//    (1)任务一

dispatch_group_async(group, queue, ^{

sleep(3);

dispatch_async(dispatch_get_main_queue(), ^{

NSLog(@"任务一处理完成");

        });

    });

//    (2)任务二

dispatch_group_async(group, queue, ^{

sleep(1);

dispatch_async(dispatch_get_main_queue(), ^{

NSLog(@"任务二处理完成");

        });

    });

    });

//    4.通过group监听什么时候所有任务全处理完成

dispatch_group_notify(group,dispatch_get_main_queue(), ^{

NSLog(@"队列中所有任务已经处理完成");

    });

以上这么多代码也全是唬人的,实际比前面的队列创建实现分线程也就是多个一个group的创建,和通过group监听。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏AndroidTv

记录 FTPClient 超时处理的相关问题问题源码跟进结论常见异常

apache 有个开源库:commons-net,这个开源库中包括了各种基础的网络工具类,我使用了这个开源库中的 FTP 工具。

32720
来自专栏塔奇克马敲代码

Windows环境下的RTKPlot_Qt版本编译时遇到的问题和解决方法

21050
来自专栏bboysoul

在树莓派上搭建使用gitlab

gitlab是一个代码托管平台,因为我的树莓派系统是安装在128G的u盘上的,用来放电影太小,但是空着就是空着了,所以还不如再搭建一个gitlab服务来存放自己...

30720
来自专栏blackpiglet

使用 pip 发布 Python 程序

写过 Python 程序的小伙伴们都知道,需要 import 个非 Python 自带的软件包时,都要用到 pip 这个程序。平时我们都是用 pip,如果我们写...

41720
来自专栏好好学java的技术栈

java工程师必备linux常用命令,这篇文章就够了

bash 是一个为GNU计划编写的Unix shell。它的名字是一系列缩写:Bourne-Again SHell — 这是关于Bourne shell(sh)...

34710
来自专栏流柯技术学院

linux下MySQL表名忽略大小写设置

最近公司项目的MySQL数据库要迁移到linux下,部署时日志总是显示报找不到一个表,用MYSQL查看明明有这个表。后来经百度,原来LINUX下的MYSQL默认...

32920
来自专栏iKcamp

iKcamp|基于Koa2搭建Node.js实战(含视频)☞ 视图Nunjucks

视频地址:https://www.cctalk.com/v/15114923888328 视图 Nunjucks 彩虹是上帝和人类立的约,上帝不会再用洪水灭人...

33480
来自专栏醒者呆

程序员必备课程——网络编程入门

关键字:互联网协议,网络分层,socket,TCP/IP协议,jdk源码,多线程,线程池,ExecutorService 本文的主要目的是面向程序员,所以...

58760
来自专栏编程

小白爬虫之爬虫快跑

使用多线程时好像在目录切换的问题上存在问题,可以给线程加个锁试试 Hello 大家好!我又来了。 你是不是发现下载图片速度特别慢、难以忍受啊!对于这种问题一般解...

20480
来自专栏码洞

RPC 服务器之【多进程描述符传递】高阶模型

今天老师要给大家介绍一个比较特别的 RPC 服务器模型,这个模型不同于 Nginx、不同于 Redis、不同于 Apache、不同于 Tornado、不同于 N...

16520

扫码关注云+社区

领取腾讯云代金券