• 多线程——NSThread


     

    什么是多线程?


    一句话,对功能的实现的流程,一个流程就是一个线程。在一个程序运行时至少有一个线程在运行,这个线程就是主线程。单线程下,只有当前的功能执行完毕,才执行下一个功能,给用户最直观的感受就是程序静止不动了。多线程就能解决这样的问题,他的原理是,吧功能分化称若干某块,然后有系统为其分配若干个线程,这些线程之间互不干扰,并行运作。提高了用户的体验感受,更加合理的发挥了系统的资源利用率。可是,这样加大了我们对多个线程之间合理安排的难度,比如说多线程的传值问题,相应处理。这就是线程管理所属的范畴。
    只有一个线程的程序是单线程程序,主线程负责程序的所有代码(UI的展示、刷新、网络请求、本地存储)。这些代码只能顺序执行,无法并发执行。主线程在程序启动的时被创建,用于执行Main 函数。
    拥有多个线程的程序被称为多线程。IOS允许用户自己开辟新的线程,相对于主线程来说这些线程被称为是子线程。主线程和子线程是独立的
    调整程序的时候,最好不要去破坏原有运行正常的代码。
    并行就是多个指令在多个处理器上执行,并发就是同一时刻只有一条指令在执行,但是多个进程指令被快速轮换,使得在宏观上似乎是同时执行的效果。
    单CPU多线程仅仅解决了流畅的问题,并没有真正的解决线程之间的阻塞等待,但是多线程就解决此问题,是并行的计算的。

    最形象的比喻来阐明上述的概念:

    你吃饭吃到一半,电话来了,你一直到吃完了以后才去接,这就说明你不支持并发也不支持并行。
    你吃饭吃到一半,电话来了,你停了下来接了电话,接完后继续吃饭,这说明你支持并发。
    你吃饭吃到一半,电话来了,你一边打电话一边吃饭,这说明你支持并行。
    
    并发的关键是你有处理多个任务的能力,不一定要同时。
    并行的关键是你有同时处理多个任务的能力。
    
    所以我认为它们最关键的点就是:是否是『同时』。
     理解并行于并发的区别


    线程的创建,并执行线程:

    - (void)viewDidLoad
    {
        [super viewDidLoad];
        for(int i = 0 ; i < 100 ; i++)
        {
            NSLog(@"===%@===%d" , [NSThread currentThread].name , i);
            if(i == 20)
            {
                // 创建线程对象
                NSThread *thread = [[NSThread alloc]initWithTarget:self
                    selector:@selector(run) object:nil];
                // 启动新线程
                [thread start];
                // 创建并启动新线程
                [NSThread detachNewThreadSelector:@selector(run) toTarget:self
                    withObject:nil];
            }
        }
    }
    
    - (void)run
    {
        for(int i = 0 ; i < 100 ; i++)
        {
            NSLog(@"-----%@----%d" , [NSThread currentThread].name, i);
        }
    }

    线程的状态:

    线程被创建启动后,他并不是一启动就进入执行状态、也不是一直处于 执行状态。一个启动的线程会处于待命状态,不可能一直霸占CPU资源,他会一直在待命——执行——待命——执行这样的循环着切换,至于何时切换则取决于系统的资源调度。只有被调度多线程才会处于执行状态。当线程对象启动 star 方法的时候,线程就处于待命状态,但是未必立即执行,要想提高执行速度中,让其立即执行,可以设定当主线程休眠0.001秒就是1毫秒的时候,立即运行子线程,使用方法为 NSThread.sleepForTimeINterval(0.001),这样主线程会在休眠1毫秒后立即执行子线程,这1毫秒内CPU在处理其他的事物并未闲置:

    NSThread* thread;
    - (void)viewDidLoad
    {
        [super viewDidLoad];
        // 创建新线程对象
        thread = [[NSThread alloc] initWithTarget:self selector:@selector(run)
            object:nil];
        // 启动新线程
        [thread start];
    }
    - (void)run
    {
        for(int i = 0 ; i < 100 ; i++)
        {
            if([NSThread currentThread].isCancelled)
            {
                // 终止当前正在执行的线程
                [NSThread exit];
            }
            NSLog(@"-----%@----%d" , [NSThread currentThread].name, i);
            // 每执行一次,线程暂停0.5秒
            [NSThread sleepForTimeInterval:0.5];
        }
    }
    - (IBAction)cancelThread:(id)sender
    {
        // 取消thread线程,调用该方法后,thread的isCancelled方法将会返回NO
        [thread cancel]; 
    }

    使用多线程去下载图片如下:

    - (IBAction)showImage:(id)sender
    {
        NSString* url = @"https://ss0.bdstatic.com/5aV1bjqh_Q23odCf/static/superman/img/logo/bd_logo1_31bdc765.png";
        // 创建新线程对象
        NSThread *thread = [[NSThread alloc]initWithTarget:self
            selector:@selector(downloadImageFromURL:) object:url];
        // 启动线程
        [thread start];
    }
    // 定义一个方法作为线程执行体。
    -(void)downloadImageFromURL:(NSString *) url
    {
        // 从网络获取数据
        NSData *data = [[NSData alloc]
            initWithContentsOfURL:[NSURL URLWithString:url]];
        // 将网络数据初始化为UIImage对象
        UIImage *image = [[UIImage alloc]initWithData:data];
        if(image != nil)
        {
            // 在主线程中执行updateUI:方法
            [self performSelectorOnMainThread:@selector(updateUI:)
                withObject:image waitUntilDone:YES]; //
        }
        else
        {
            NSLog(@"---下载图片出现错误---");
        }
    }
    -(void)updateUI:(UIImage*) image
    {
        self.iv.image = image;
    }

    取消线程如下:

    NSThread* thread;
    - (void)viewDidLoad
    {
        [super viewDidLoad];
        // 创建新线程对象
        thread = [[NSThread alloc] initWithTarget:self selector:@selector(run)
            object:nil];
        // 启动新线程
        [thread start];
    }
    - (void)run
    {
        for(int i = 0 ; i < 100 ; i++)
        {
            if([NSThread currentThread].isCancelled)
            {
                // 终止当前正在执行的线程
                [NSThread exit];
            }
            NSLog(@"-----%@----%d" , [NSThread currentThread].name, i);
            // 每执行一次,线程暂停0.5秒
            [NSThread sleepForTimeInterval:0.5];
        }
    }
    - (IBAction)cancelThread:(id)sender
    {
        // 取消thread线程,调用该方法后,thread的isCancelled方法将会返回NO
        [thread cancel]; 
    }

      待续。。。。

     



  • 相关阅读:
    C语言中指针*p[N], (*P)[N],及**p的区别
    一个酷炫的,基于HTML5,Jquery和Css的全屏焦点图特效,兼容各种浏览器
    day10函数作业详解
    day9函数作业详解
    day7计算作业详解
    day6作业详解
    通过Web安全工具Burp suite找出网站中的XSS漏洞实战(二)
    使用Docker快速部署ELK分析Nginx日志实践(二)
    java 字符串转运算符
    生成给定范围的n随机整数
  • 原文地址:https://www.cnblogs.com/benpaobadaniu/p/4853047.html
Copyright © 2020-2023  润新知