iOS多线程

半城伤御伤魂 提交于 2021-02-18 11:51:06

//

//  ViewController.m

//  UI_Lesson_21

//

//  Created by xalo on 15/10/7.

//  Copyright © 2015 . All rights reserved.

//


#import "ViewController.h"


@interface  ViewController ()

@property (retainnonatomicIBOutlet UIImageView *iamgeView;

@property (retainnonatomicIBOutlet UIActivityIndicatorView *activitayIndicator;


@end


@implementation ViewController




- (IBAction)HhandleButtonAction:(id)sender {

    // 应用程序进程会默认开辟一个线程 -- 主线程   主线程的作用是更新UI姐买呢 如果应用程序在允许过程中不开辟其他线程  只有主线程可以完成任务炒作 这种情形称为单线程应用  单线程会出现一定程度的代码阻塞  导致界面假死

    

   //开辟子线程方法一:

    //开辟新的子线程并附加对应的方法  等待被执行

//    NSThread *aTharead = [[[NSThread alloc]initWithTarget:self selector:@selector(calculate) object:nil] autorelease];

//    //为子线程对象发送start消息 开启线程 执行相关方法

//    //添加线程对象名

//    aTharead.name = @"我是NO.1";

//    //开启线程

//    [aTharead start];

//    

//    //开辟子线程方法二:

//    [NSThread detachNewThreadSelector:@selector(calculate) toTarget:self withObject:nil];

    //如果子线程的对应方法 内部 在双创建带有autorelease的对象  必须要添加创建一个自动释放池   否则对象无法释放

    

//    [NSThread detachNewThreadSelector:@selector(downloadImage) toTarget:self withObject:nil];

    

    /*

    [self.activitayIndicator startAnimating];

   

    //创建NSInvocationOperation

    NSInvocationOperation *invoOperation = [[[NSInvocationOperation alloc]initWithTarget:self selector:@selector(calculate) object:nil] autorelease];

//    [invoOperation start];

    //创建NSBlockOperation

    NSBlockOperation *blockOperation =[NSBlockOperation blockOperationWithBlock:^{

        [self downloadImage];

    }];

//        [blockOperation start];

    //创建操作队列  通过操作队列 完成操作对象的执行

    //创建主线程队列(任务主线程执行)

//    NSOperationQueue *queue = [NSOperationQueue mainQueue];

     //自己创建队列 (任务会提交子线程执行)

    NSOperationQueue *queue = [[[NSOperationQueue alloc]init] autorelease];//自己创建的操作队列在执行相关的操作对象是  会根据需求开辟子线程去执行

    //设置最大并发数

    //最大并发数为1  表示队列被顺序执行  只有前一个操作完成后才继续执行下一个操作

    [queue setMaxConcurrentOperationCount:2];

    //设置操作队列优先级

    [blockOperation setQueuePriority:NSOperationQueuePriorityVeryHigh];

    [invoOperation setQueuePriority:NSOperationQueuePriorityVeryLow];

    [queue addOperation:blockOperation];

    [queue addOperation: invoOperation];

     */

    

    [self grandCentralDispatchMethod];

    


}



//GCD的核心是使用分发队列来管理任务的执行  分发队列分为两种 : 一种是serial(串行)  一种是concurrent(并发两种都严格遵守FIFO(先进先出)

- (void)grandCentralDispatchMethod{

    /*

    //1获取serial queue的两种方式

    //获取主线程队列  mainQueue 会在主线程中执行  :主线程会执行mainQueue中的各个任务

   dispatch_queue_t mainQueue = dispatch_get_main_queue();//dispatch_get_main_queue获取主线程队列 串行队列


    //为主线程提交任务 任务以block 形式提交

     //dispatch_async异步执行  主线程交替执行函数 (不会卡顿)(_async并发执行)

    dispatch_async(mainQueue, ^{

       NSLog( @"第二个任务");

        [self calculate];

    });//block中写要被执行的代码片段  也可以是方法的调用

    

     //dispatch_sync同步提交任务函数(_sync串行执行)

    dispatch_sync(mainQueue, ^{

        NSLog( @"第三个任务");

        [self downloadImage];

    });

    */

  /*

    //除了可以获取 主队列的这种串行队列  还可以自己根据需求创建串行队列

    //自定义的串行队列在分发执行任务是通过开辟子线程执行的

   //GCD队列(dispatch queue) dispatch_queue_t

    dispatch_queue_t mySerialQueue = dispatch_queue_create("cGCD.mySerialQueue", DISPATCH_QUEUE_SERIAL);//dispatch_queue_create 创建队列方法 //参数一  给当前创建的队列起名字  苹果推荐使用反向的域名形式   //参数二 DISPATCH_QUEUE_SERIAL 创建的队列类型private dispatch queues串行队列  指定当前创建队列的类型 分为Srial concurrent 两种(:串行和并发 )

   

    dispatch_async(mySerialQueue, ^{

        NSLog( @"first mission :%@", [NSThread isMainThread] ? @"main thread":@"isn't main tread");

    });

    dispatch_async(mySerialQueue, ^{

        NSLog( @"second mission :%@", [NSThread isMainThread] ? @"main thread":@"isn't main tread");

    });

    dispatch_async(mySerialQueue, ^{

        NSLog( @"thread mission :%@", [NSThread isMainThread] ? @"main thread":@"isn't main tread");

    });

   */

    

    //获取并发队列的两种方法

    /*

    dispatch_queue_t globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0);//dispatch_get_global_queue  获取global dispatch queue  并发队列//第一个参数是用来控制队列的优先级   //参数二是苹果的预留参数  未来才会使用  现在设置为0(必须)

    //globalQueue作为并发队列  会开辟是若干/个子线程并发执行 多个提交的任务(开始较晚的不一定晚结束  开始早的不一定会最先结束 )

    dispatch_async(globalQueue, ^{

         NSLog( @"first mission :%@", [NSThread isMainThread] ? @"main thread":@"isn't main tread");

        [self downloadImage];


    });

    dispatch_async(globalQueue, ^{

        NSLog( @"second mission :%@", [NSThread isMainThread] ? @"main thread":@"isn't main tread");

        [self calculate];

    });

     */

    //自己创建并发队列

    dispatch_queue_t myConcurrentQueue = dispatch_queue_create("com..GCD.myconcurrentQueue"DISPATCH_QUEUE_CONCURRENT);//dispatch_queue_create  创建队列  "com..GCD.myconcurrentQueue"  给当前创建的队列起名字  苹果推荐使用反

    /*

     向的域名形式   DISPATCH_QUEUE_CONCURRENT 队列类型 CONCURRENT并发

    dispatch_async(myConcurrentQueue, ^{

        NSLog( @"first mission :%@", [NSThread isMainThread] ? @"main thread":@"isn't main tread");

        [self downloadImage];

        

    });

    dispatch_async(myConcurrentQueue, ^{

        NSLog( @"second mission :%@", [NSThread isMainThread] ? @"main thread":@"isn't main tread");

        [self calculate];

    });

    

    //延时提交某个任务到分发队列中(延时执行任务可以在mainQueue中正常执行   在自定义的队列中执行就会出现问题)

    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{

        NSLog( @"延时3s执行任务");

    });

    */

    /*

    //创建任务组

    dispatch_group_t group = dispatch_group_create();

    dispatch_group_async(group, myConcurrentQueue, ^{

        NSLog( @"任务一");

    });

    dispatch_group_async(group, myConcurrentQueue, ^{

        NSLog( @"任务二");

        [self calculate];

    });

    //dispatch_group_notify 中的方法会等待group中的成员执行完了之后再执行

    dispatch_group_notify(group, myConcurrentQueue, ^{

        NSLog( @"任务三");

    });

     */

    

    

    //为了保证数据访问是的安全性 , 可以使用serial queue 来解决访问安全性问题

    //serial queue 缺陷:后面的任务必须等待前面的任务结束后才能执行  降低数据读取的效率

    //如果只是读取数据  适合使用concurrent queue 来执行

    

    dispatch_async(myConcurrentQueue, ^{

        NSLog@"读取数据任务一");

    });

    dispatch_async(myConcurrentQueue, ^{

        NSLog@"读取数据任务二");

    });

    dispatch_async(myConcurrentQueue, ^{

        NSLog@"读取数据任务三");

    });

    //dispatch_barrier_async (它之前的并发执行完---它执行---它执行完它之后的再并发执行并发执行中这个方法会执行结束之后之后的方法才能执行 有利于保证数据安全  会等待它之前提交的任务并发执行结束后才开始执行 并且执行完成之后才开始其之后提交的任务 像一道墙  隔开了之前和之后提交的任务 这样的操作可以保证读写安全性 也可以提高读写的效率

    dispatch_barrier_async(myConcurrentQueue, ^{

        NSLog@"写入数据任务");

        [self calculate];

    });

    dispatch_async(myConcurrentQueue, ^{

        NSLog@"读取数据任务四");

    });

    dispatch_async(myConcurrentQueue, ^{

        NSLog@"读取数据任务五");

    });

    

    for (int i = 0 ;i < 10; i ++) {

        static dispatch_once_t  onceToken;

        dispatch_once(&onceToken, ^{

            NSLog(@"任务被执行%d", i+ 1);

        });

    }

    /*

    //苹果推荐使用dispatch_once来定义单例方法

    +(id)shareInstance{

        static FooClass *object = nil;

        static dispatch_once_t onceToken;

        dispatch_once(&onceToken, ^{

            object = [[FooClass alloc]init];

            

        });

        return object;

    }

     */

}




- (void)downloadImage{

    NSLog@"下载图片");

    //同步

    NSData *imageData = [NSData dataWithContentsOfURL:[NSURL URLWithString: @"http://www.pp3.cn/uploads/allimg/111111/100519C19-1.jpg"]];


    //回到主线程  由主线程取更新UI界面

    [self performSelectorOnMainThread:@selector(updataUserInterface:) withObject:imageData waitUntilDone:YES];

}

- (void)updataUserInterface:(NSData *)data{

    [self.activitayIndicator stopAnimating];;

    self.iamgeView.image = [UIImage imageWithData:data];

}



- (void)calculate{

    NSLog( @"计算");

//    NSLog( @"线程:%@ 是否是主线程:%@", [NSThread currentThread], [NSThread isMainThread]?@"": @"");

    NSInteger count = 0 ;

    for (NSInteger i = 0 ; i < 635500000; i ++) {

        count += i ;

//        @autoreleasepool {

//            NSArray *array = [[[NSArray alloc]init] autorelease];

//         

//        }

    }

    NSLog( @"%ld", count);

}


- (void)viewDidLoad {

    [super viewDidLoad];

    // Do any additional setup after loading the view, typically from a nib.

}


- (void)didReceiveMemoryWarning {

    [super didReceiveMemoryWarning];

    // Dispose of any resources that can be recreated.

}


- (void)dealloc {

    [_iamgeView release];

    [_activitayIndicator release];

    [super dealloc];

}

@end




易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!