多线程技术(一)

来源:互联网 发布:prisma背后的算法 编辑:程序博客网 时间:2024/05/04 19:06

进程Process: 已经启动的应用程序叫进程

线程Thread: 一段可执行的代码序列(任务 / 代码)


进程和线程的区别:

1. 从数量角度: 一个进程可以包含至少一个线程[1, x)

2. 从执行任务角度: 进程不执行任务,分配资源(根据不同的操作系统);线程执行任务


主线程:当一个程序启动时,就有一个进程被操作系统(OS)创建,与此同时一个线程也立刻运行,该线程通常叫做程序的主线程(Main Thread),因为它是程序开始时就执行的,如果你需要再创建线程,那么创建的线程就是这个主线程的子线程。


主线程和子线程的责任分工

1. 主线程责任(用户 /  交互):

a. 所有和界面相关的逻辑由主线程执行(UIKit Framework)

b. 响应用户的事件(滚动 / 拖拽 / 点击。。。)

2. 子线程(耗时操作)

a. 下载图片 / 音频文件 / for循环逻辑

Xcode 启动之后成为进程,分配线程的资源

1. 主线程: 1M(内存)

2. 子线程: 512KB(内存)


代码可以启动多少个子线程?

3 ~ 5 个子线程


多线程Multi-Thread:


iOS提供多少个创建子线程技术?

一、pthread

1. pthread(了解)

POSIX Thread(Portable Operation System Interface):可移植的操作系统接口线程

2.特点:

优点: 可移植性

缺点: 基于C语言, 底层; 功能少


Demo04_pthread

分析:

1. 主线程阻塞:有其他的耗时操作占用着主线程

2. 所有的事件 / 任务都会放到队列中(主线程操作的队列叫做主队列);  队列中的任务以FIFO(先进先出)方式响应(执行)

3. 让子线程执行耗时操作不会造成主线程阻塞



二、NSThread

1. NSThread特点:

优点: 基于OC语言;

缺点: 需要管理线程的生命周期、同步、加锁问题,这会导致一定的性能开销 

2. 如何使用?

a. 如何创建NSThread 类型的子线程方式(alloc / init)

b. 如何调用NSThread方法, 来判断代码是由主线程还是子线程执行

{number = 1, name = main}

{number = 2, name = (null)}


通过[NSThread currentThread]的返回值判定由主线程还是子线程执行

a. number = 1  -> 主线程

b. number不是1 -> 子线程


Demo01_pthread

<span style="font-size:14px;">//主线程MainThread- (IBAction)executeTimingOperation:(id)sender {    //创建for循环模拟耗时操作    for (int i=0; i<5000; i++) {        NSLog(@"执行次数:%d", i);    }}//<#void *(*)(void *)#>void *task(void *data){    //验证传参    printf("验证传参:%s", (char *)data);    //耗时操作    for (int i=0; i<20000; i++) {        NSLog(@"执行次数:%d", i);    }    return NULL;}//子线程- (IBAction)executeTimingOperationByPthread:(id)sender {    //1.创建子线程对象    /*        参数一:指定pthread_t类型的子线程地址        参数二:指定线程特定属性(占用内存空间)        参数三:函数声明        参数四:传给上面函数的参数     */    pthread_t pthread;    char *data = "Hello";    pthread_create(&pthread, NULL, task, data);    //2.把耗时操作给子线程执行}</span>



Demo02_NSThread

<span style="font-size:14px;">// 1.创建NSThread对象    NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(downloadImage:) object:@"Hello"];    //设置子线程的名字    thread.name = @"这是我的子线程";    //3.启动子线程的任务Task    [thread start];        NSLog(@"------由线程执行如下代码:%@", [NSThread currentThread]);</span>

<span style="font-size:14px;">//2.将耗时操作指定给子线程方法(对象)- (void)downloadImage:(NSString *)string{    //由子线程执行    NSLog(@"由子线程执行如下代码:%@", [NSThread currentThread]);    //让子线程休眠5s    [NSThread sleepForTimeInterval:5];        for (int i=0; i<5; i++) {        NSLog(@"执行次数:%d", i);                if (i == 1) {            //线程退出            [NSThread exit];        }    }}</span>

Demo03_NSThread下载图片

<span style="font-size:14px;">- (IBAction)downloadImageByNSThread:(id)sender {    //1.NSThreaad对象    NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(downloadImage) object:nil];    //2.执行下载逻辑        //3.启动子线程    [thread start];}- (void)downloadImage{    //NSString -> NSURL -> NSData -> UIImage    NSString *imageStr = @"http://www.egouz.com/uploadfile/2015/0305/20150305103626911.jpg";    NSURL *imageUrl = [NSURL URLWithString:imageStr];    //如下方法是耗时的操作    NSData *imageData = [NSData dataWithContentsOfURL:imageUrl];    UIImage *image = [UIImage imageWithData:imageData];    /*        由子线程回到主线程,赋值给imageView        主线程执行任务优先级高于子线程任务     */    //子线程回到主线程方式一    [self performSelectorOnMainThread:@selector(returnMainThread:) withObject:image waitUntilDone:YES];    }- (void)returnMainThread:(UIImage *)image{    NSLog(@"赋值:%@", [NSThread currentThread]);    self.imageView.image = image;}</span>


  坑:

  1. 在Info.plist中添加允许HTTP不安全协议的请求,方式如下

 

  2.和UIKit相关的操作需要从子线程回到主线程(原理)

     [selfperformSelectorOnMainThread:@selector(returnMainThread:)withObject:imagewaitUntilDone:YES];


0 0
原创粉丝点击