IOS培训

亿元级外企ios培训企业

  • 全国服务监督电话4001118989
  • IOS多线程的那些事

    发布:佚名  来源:达内  时间: 2015年07月27日

  • 此文的目的,不是为了深度解析多线程,只是让大家看到一些多线程实现的内容,和基本定义。...

  • 此文的目的,不是为了深度解析多线程,只是让大家看到一些多线程实现的内容,和基本定义。
    也许很多人奇怪,多线程是为了干啥,简单来讲,一般是两个目的:1、最大化利用有限硬件资源,节约程序执行时间。例如:某个程序的逻辑,单个线程需要执行1小时,而且硬件资源的大部分都在闲置,所以我们就把闲置的资源调动起来,开辟多线程,使得执行时间小于1小时。
    2、实现良好的 User Interface feeling。例如:我们在主线程执行 一个 一小时下载的时候,会发现,界面卡主了,不能动了。这样的程序自然会让人极其烦躁。利用多线程,就可以让下载在后台运行,界面依然可以操作。

    所以本人写得内容,主要是总结了多线程的几种定义,以及哪些定义可以不阻塞主线程,哪些时候任务是串行,哪些时候任务是并行。

    附件代码,把主线程的执行,用移动图片来实现。因为帖子字数限制,只粘贴了部分代码。
    @interface ViewController ()
    @property (weak, nonatomic) IBOutlet UIImageView *imageView;
    @property (nonatomic,assign) int showNumber;
    @property (nonatomic,assign) int showOtherNumber;
    @property (nonatomic,strong) NSLock* lock;
    @end

    @implementation ViewController

    - (void)viewDidLoad {
        [super viewDidLoad];
    }

    -(void) touchesBeganNSSet *)touches withEventUIEvent *)event
    {
        UITouch* touch = [touches anyObject];
        CGPoint point = [touch locationInView:self.view];
       
        self.imageView.center = point;
    }

    -(void)touchesMovedNSSet *)touches withEventUIEvent *)event
    {
        UITouch* touch = [touches anyObject];
        CGPoint point = [touch locationInView:self.view];
       
        self.imageView.center = point;
    }
    - (IBAction)btn_Pthread_Clickedid)sender {
       
        //1、创建 PThread 对象
        pthread_t myPthread;
        int error = pthread_create(&myPthread,NULL,task,NULL);
       
        if(error != 0)
        {
            NSLog(@"创建错误!~");
        }
        else
        {
            NSLog(@"线程完成");
        }
       
    }

    void* task(void* data)
    {
        //循环打印10次,每次睡眠1秒钟。
        //当控制器开始打印的时候,我们可以尝试,是否可以移动图片
        for (int i = 0; i < 10 ; i++) {
            [NSThread sleepForTimeInterval:1];
            NSLog(@"%d,%@",i+1,[NSThread currentThread]);
        }
       
        //在打印的过程中,我们发现,图片可以移动,而且通过打印信息可以知道打印是由 非主线程执行的。
        //那么PThread 创建的线程,是异步执行的。
        //异步和同步的区别,我们后面GCD在详细讲
       
        return 0;
       
    }

    - (IBAction)btn_Thread1_Clickedid)sender {
       
        //创建NSThread对象
        NSThread* thread = [[NSThread alloc]initWithTarget:self selectorselector(task) object:nil];
       
        //这种方法可以设置thread 的其他属性,例如 优先级,size等。
        //[thread setThreadPriority:0.8]; 0-1.0
        //thread.stackSize = 16 * 1024;
       
        [thread start];
       
        //结论 子线程执行的时候,图片依然可以移动,那么表示子线程没有阻塞主线程。是异步执行
    }

    -(void) task
    {
        //循环打印10次,每次睡眠1秒钟。
        //当控制器开始打印的时候,我们可以尝试,是否可以移动图片
        for (int i = 0; i < 10 ; i++) {
            [NSThread sleepForTimeInterval:1];
            NSLog(@"%d,%@",i+1,[NSThread currentThread]);
        }
    }

    - (IBAction)btn_Thread2_Clickedid)sender {
        //创建NSThread 对象并执行
        [NSThread detachNewThreadSelectorselector(task) toTarget:self withObject:nil];
       
        //结论 子线程执行的时候,图片依然可以移动,那么表示子线程没有阻塞主线程。是异步执行
    }

    - (IBAction)btn_Thread3_Clikedid)sender {
       
        //后台执行task
        [self performSelectorInBackgroundselector(task) withObject:nil];
       
        //从打印以及 可以移动图片可知,此方法后台创建了子线程,而且是异步执行。
    }

    - (IBAction)btn_ThreadAndLock_Clickedid)sender {
       
        //在此我们先查看一个事例,如果不加锁,两个并行异步的线程访问到同一个资源时候,可能会导致脏数据(请百度)产生。
       
        //在此之前我们定义一个属性 int showNumber;
        //初始化showNumber 为0;
    //    self.showNumber = 0;
    //   
    //    NSThread* firstThread = [[NSThread alloc]initWithTarget:self selectorselector(task2) object:nil];
    //   
    //    NSThread* secondThread = [[NSThread alloc]initWithTarget:self selectorselector(task2) object:nil];
    //   
    //    [firstThread start];
    //    [secondThread start];
       
       
       
        //执行下列代码,请把 first 和 second 的内容注释。
       
         //初始化Lock
         self.lock = [[NSLock alloc]init];
         
         //初始化showOtherNumber
         self.showOtherNumber = 0;
         
         NSThread* thirdThread = [[NSThread alloc]initWithTarget:self selectorselector(task3) object:nil];
         
         NSThread* forthThread = [[NSThread alloc]initWithTarget:self selectorselector(task3) object:nil];
         
         [thirdThread start];
         [forthThread start]
    }
    -(void) task2
    {
        //偏移showNumber ,如果showNumber = 0 就 + 1,如果showNumber = 1 就 - 1; 如果正偏移量超过 1,就结束。
       
        while (1) {
            
            if(self.showNumber == 0)
            {
                NSLog(@"%@ ---> %d",[NSThread currentThread],++self.showNumber);
            }
            else if(self.showNumber == 1)
            {
                NSLog(@"%@ ---> %d",[NSThread currentThread],--self.showNumber);
            }
            else
            {
                NSLog(@"%@ ---> %d",[NSThread currentThread],self.showNumber);
                return;
            }
        }
       
        //我们参照逻辑,showNumber初始值是 0,那么在执行++操作后,showNumber的下一次执行就是 --,按照逻辑,showNumber永远在0,1之间徘徊,而且打印的结果应该是 0,1的交叉顺序重复
       
        //但是在运行后,我们发现终于发生了可怕的事情,showNumber 居然 变成了2,一个我们意料之外的值。 那么可见在两条线程同时执行task2的时候,产生了脏数据 2。 如果线程更多,这个错误可能会更大。
       
        //现实生活中很多例子不允许我们有这样的结果,例如春节买火车票,买电影票,甚至是银行的存款,我们绝对不能允许这些脏数据的存在,因为它不可预料。 所以请参见下一个task3,加锁之后的结果。
    }

    @end
  • 上一篇:为梦想扬帆起航!

    下一篇:几种常用的获取自定义TableViewCell

网站导航
2001-2016 达内时代科技集团有限公司 版权所有 京ICP证8000853号-56