iOS程序猿iOS学习iOS 开发成长中心

iOS多线程编程

2016-11-07  本文已影响79人  7937

一、多线程概述

  1. 线程之间容易共享内存,进程间不能.
  2. 充分发挥多核处理器的优势,不同任务分配给不同处理器,进入“并行运算”的状态
  3. 将耗时、轮询或并发需求高的任务分配到其他线程进行,主线程负责统一更新界面,这样使用户体验更好.
  1. 占内存(默认住线程1M 子线程512K)
  2. CPU开销大(一般同时开启线程小于5个).
  3. 程序设计变得复杂.

二、iOS多线程技术

三、NSThread三种创建线程的方法及阻塞线程的测试

在storyboard里放一个Button和一个Text View(用来测试线程的阻塞)

#import "ViewController.h"

@interface ViewController ()

@end

@implementation ViewController

- (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.
}

//获取当前、主线程
- (IBAction)ClickBtn:(id)sender {
    NSThread *current = [NSThread currentThread];
    NSLog(@"Current thread %@ ",current);
    
    NSThread *main = [NSThread mainThread];
    NSLog(@"Main thread %@",main);    

    [self threadCreate1];

    //第二种方法  [self threadCreate2];
    //第三种方法  [self threadCreate3];
    //测试阻塞方法  [self threadTest];
}

//输出当前线程
- (void)run:(NSString *)param{
    NSThread *current = [NSThread currentThread];
    for(int i = 0; i<10; i++){
        NSLog(@"%@ run %@",current,param);
    }
}

- (void)threadCreate1{
    NSThread *threadA =[[NSThread alloc]initWithTarget:self selector:@selector(run:) object:@"线程A参数"];
    threadA.name = @"线程A";
    [threadA start];
    
    NSThread *threadB =[[NSThread alloc]initWithTarget:self selector:@selector(run:) object:@"线程B参数"];
    threadB.name = @"线程B";
    [threadB start];
}

- (void)threadCreate2{
    [NSThread detachNewThreadSelector:@selector(run:) toTarget:self withObject:@"方式2参数"];
}

//隐式创建并启动线程,在后台线程中执行
- (void)threadCreate3{
    [self performSelectorInBackground:@selector(run:) withObject:@"方式3参数"];
}

//测试阻塞线程
- (void)threadTest{
    NSLog(@"%@",[NSThread currentThread]);
    for (int i=0 ; i<10000; i++) {
        NSLog(@"-----%d",i);
    }
}              
@end

四、线程间的安全隐患

加锁前后示意图

五、线程间的通信

GCD(Grand Central Dispatch)

一、队列(Dispatch Queue)

二、创建队列

1.获取全局并发队列(Global Concurrent Dispatch Queue)
2.创建串、并行队列(Serial And Concurrent Dispatch Queue)
3.获取主队列

三、提交任务

1.同步添加任务到队列,不具备开启新线程能力,阻塞调用线程直到相应任务完成
2.异步在新线程执行任务,可以让线程池立即执行,调用其他线程做其他事情,应尽可能使用异步.
#import "ViewController.h"

@interface ViewController ()

@end

@implementation ViewController

dispatch_queue_t serialQueue;
dispatch_queue_t globalQueue;

- (void)viewDidLoad {
    [super viewDidLoad];
    //创建串行队列
    serialQueue = dispatch_queue_create("serQ", DISPATCH_QUEUE_SERIAL);
    //全局并发队列
    globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
}

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

//串行异步执行任务
- (IBAction)asynSerial:(id)sender {
    dispatch_async(serialQueue, ^{
        for (int i = 0; i<10; i++) {
            NSLog(@"%@  task1  %d",[NSThread currentThread],i);
        }
    });
    dispatch_async(serialQueue, ^{
        for (int i = 0; i<10; i++) {
            NSLog(@"%@  task2  %d",[NSThread currentThread],i);
        }
    });
}

//并行异步执行任务
- (IBAction)asynConcurrent:(id)sender {
    dispatch_async(globalQueue, ^{
        for (int i = 0; i<10; i++) {
            NSLog(@"%@  task1  %d",[NSThread currentThread],i);
        }
    });
    
    dispatch_async(globalQueue, ^{
        for (int i = 0; i<10; i++) {
            NSLog(@"%@  task2  %d",[NSThread currentThread],i);
        }
    });
}
@end

四、单次或重复执行任务

五、调度队列组

NSOperation

新建一个继承NSOperation的类.

//Download.h

#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>

@class Download;

//定义代理
@protocol DownloadDelegate <NSObject>

//下载方法
- (void)download:(Download *)operation image:(UIImage *)image;

@end

@interface Download : NSOperation

@property (nonatomic, strong)NSString *url;

//代理属性
@property (nonatomic, weak)id<DownloadDelegate>delegate;
@end
//Download.m

#import "Download.h"

@implementation Download

//重写main方法
- (void)main
{
    @autoreleasepool {
        NSURL *url = [NSURL URLWithString:self.url];
        NSData *data = [NSData dataWithContentsOfURL:url];
        UIImage *image = [UIImage  imageWithData:data];
        [[NSOperationQueue mainQueue]addOperationWithBlock:^{
            NSLog(@"download finished");
            if ([self.delegate respondsToSelector:@selector(download:image:)]) {
                [self.delegate download:self image:image];
            }
        }];
    }
}
@end

在storyboard中放一个Image View

//ViewController.m

#import "ViewController.h"
#import "Download.h"

@interface ViewController ()<DownloadDelegate>

@property (strong, nonatomic) IBOutlet UIImageView *imageView;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    //创建队列
    NSOperationQueue *queue = [[NSOperationQueue alloc]init];
    
    //下载操作
    Download *operation = [[Download alloc]init];
    operation.delegate = self;
    operation.url =@"https://mir-s3-cdn-cf.behance.net/project_modules/max_1200/943ff442182699.57c4298d2eb2a.png" ;

    //操作加到队列中
    [queue addOperation:operation];
}

//执行操作
- (void)download:(Download *)operation image:(UIImage *)image{
    self.imageView.image = image;
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
}
@end
运行结果

若提示:
App Transport security has blocked a cleartext HTTP (http://) resource load since it is insecure. Temporary exceptions can be configured via your app's Info.plist file.
解决方法:


加上Allow Arbitrary Loads 并设置为YES
上一篇 下一篇

猜你喜欢

热点阅读