zoukankan      html  css  js  c++  java
  • NSThread

    任何一个 iOS 应用程序都是由一个或者多个线程构成的。无论你是否显示的使用了多线程编程技术,至少有 1个 线程被创建。该线程叫做”main UI 线程”,被附加到主事件处理循环中(main run loop)。

     
    多线程就是为了提高引用程序的工作效率!避免阻塞主线程!
     
    当我们没有用任何多线程技术的话,默认情况下,是在程序的主线程中执行相关操作!
     
    主线程执行任务
     
    贴个单线程(主线程)执行任务的例子:
     

    // 任务1

    - (void) firstCounter{

        NSUInteger counter = 0;

        for (counter = 0;

             counter < 1000;

             counter++){

            NSLog(@"First Counter = %lu", (unsigned long)counter); }

    }

    // 任务2

    - (void) secondCounter{

        NSUInteger counter = 0;

        for (counter = 0;

             counter < 1000;

             counter++){

            NSLog(@"Second Counter = %lu", (unsigned long)counter); }

    }

    // 任务3

    - (void) thirdCounter{

        NSUInteger counter = 0;

        for (counter = 0;

             counter < 1000;

             counter++){

            NSLog(@"Third Counter = %lu", (unsigned long)counter);

        }

    }

     
    调用:
     

    - (void)viewDidLoad{

        [super viewDidLoad];

        

        [self firstCounter];

        [self secondCounter];

        [self thirdCounter];

    }

     
    输出:
     

     First Counter = 0

    ... ...

     First Counter = 999

     

     Second Counter = 0

    ... ...

     Second Counter = 999

     

     Third Counter = 0

    ... ...

     Third Counter = 999

     

    你会看到第一个计时器运行完毕,然后是第二个计时器,最后是第三个计时器。也就是说这些循环是在同一个线程运行的。线程代码中被执行的每一块代码一直在运行,直到循 环结束。 

    使用多线程执行任务
     
    贴:

    - (void)viewDidLoad{

        [super viewDidLoad];

        

        // 开辟一个线程,执行任务

        [NSThread detachNewThreadSelector:@selector(firstCounter)

                                 toTarget:self

                               withObject:nil];

        

        // 开辟一个线程,执行任务

        [NSThread detachNewThreadSelector:@selector(secondCounter)

                                 toTarget:self

                               withObject:nil];

        

        // 该方法在主线程中执行

        [self thirdCounter];

    }

     
    输出:
     
    ... ...

     First Counter = 997

     Second Counter = 984

     First Counter = 998

     Second Counter = 985

     First Counter = 999

    ... ...
     
    可以看到3个线程并行执行。
     
    在后台创建一个线程来执行任务
     

    贴:

    [self performSelectorInBackground:@selector(firstCounter) withObject:nil];

        [self performSelectorInBackground:@selector(secondCounter) withObject:nil];

        [self performSelectorInBackground:@selector(thirdCounter) withObject:nil];

     

    performSelectorInBackground方法为我们在后台创建了一个线程。这等同于 我们为 selectors 创建一个新的线程。 但是要记住,必须在调用的方法中加上自动释放池!

    // 任务1

    - (void) firstCounter{

        @autoreleasepool {

            // MyCode

        

        }

    }

    来释放掉我们在操作过程中的内存!否则会发生内存泄漏!
     
    对于使用线程的一些建议:
     
    1.当我们需要中途停止线程时,我们不应该调用exit方法,而是调用cancel方法。因为,如果我们直接调用
    exit方法的话,线程是直接退出,而没有机会去执行清理操作,可能会产生内存泄漏!
     
    2.我们必须要清楚这么一个现象!
    当线程在执行过程中,如果被sleepForTimeInterval后,线程将会被进入休眠。那么在它休眠期间又被cancel后,那么,事实上,线程在醒来后,任然会执行完它的操作。
     
    还是贴给小代码:
     
    线程方法:

    // 线程执行

    - (void) threadEntryPoint{

        @autoreleasepool {

            NSLog(@"Thread Entry Point");

            while ([[NSThread currentThread] isCancelled] == NO){

                [NSThread sleepForTimeInterval:10];

                NSLog(@"Thread Loop");

            }

            NSLog(@"Thread Finished");

        }

    }

    // 停止线程

    - (void) stopThread{

        NSLog(@"Cancelling the Thread");

        [self.myThread cancel];

        NSLog(@"Releasing the thread");

        self.myThread = nil;

    }

     
    调用:

    - (void)viewDidAppear:(BOOL)animated{

        

        // 创建线程

        self.myThread = [[NSThread alloc]

                         initWithTarget:self

                         selector:@selector(threadEntryPoint)

                         object:nil];

        

        // 开启线程

        [self.myThread start];

        // 让线程3秒后取消

        [self performSelector:@selector(stopThread) withObject:nil

                   afterDelay:3.0f];

    }

     
    输出:

     Thread Entry Point

     Cancelling the Thread

     Releasing the thread

     Thread Loop

     Thread Finished

     
    注意,输出的飘红部分,我明明调用了[NSThread sleepForTimeInterval:10];方法让线程进入休眠状态。并且让线程已经执行了stopThread方法中的[self.myThread cancel];方法把线程给取消了。但是,线程在被唤醒后,任然执行了后面的代码!
     
     
    说真的,我也不晓得怎么回事!这当然是一个很奇葩的问题!但是,在现实编程中,确实会遇到!
     
    只有改良的办法:多加一层判断!!!
     

    - (void) threadEntryPoint{

        @autoreleasepool {

            NSLog(@"Thread Entry Point");

            while ([[NSThread currentThread] isCancelled] == NO){

                [NSThread sleepForTimeInterval:10];

                if ([[NSThread currentThread] isCancelled] == NO){

                    // 做一个改进,在需要执行的代码中,多加一层判断。

                    NSLog(@"Thread Loop");

                }

            }

            NSLog(@"Thread Finished");

        }

    }

  • 相关阅读:
    sql导数据 自增长
    只能在执行 Render() 的过程中调用 RegisterForEventValidation
    JS获取DropDownList的值
    解决IE6、IE7、IE8、Firefox兼容的两种方案
    C#日期格式化
    页面弹出窗口刷新父页面方式小结
    Dictionary Queue Stack SortedList ArrayList
    asp.net水晶报表推模式加载报表数据代码段
    JS隐藏工具栏菜单栏
    解决在SQL Server 2000的存储过程不能调试
  • 原文地址:https://www.cnblogs.com/deng37s/p/4600635.html
Copyright © 2011-2022 走看看