美文网首页
iOS多线程

iOS多线程

作者: 我不白先生 | 来源:发表于2020-12-03 15:13 被阅读0次

耗时操作:1.网络请求 2.大量运算3.大文件相关4睡眠代码
1.不能在主线程中做耗时的操作
2.不能在子线程中修改页面的操作
三种开启线程的方式:
1.NSThread 没有线程队列的概念

- (IBAction)clicked:(UIButton *)sender {
    //[NSThread sleepForTimeInterval:5];
    NSLog(@"a");
    [NSThread detachNewThreadWithBlock:^{
        for (NSInteger i=0; i<5; i++) {
            [NSThread sleepForTimeInterval:1];
            NSLog(@"a%ld",i);
           //回到主线程
            [self performSelectorOnMainThread:@selector(updateUI:) withObject:@(i) waitUntilDone:NO ];
        }
    }];
    NSLog(@"b");
    //[NSThread detachNewThreadSelector:@selector(newThreadWithMethod:) toTarget:self withObject:s];
}

- (void)viewDidLoad {
    [super viewDidLoad];    
}
-(void)updateUI:(NSNumber *)number{
    int i = [number intValue];
    UIView *v = [[UIView alloc]initWithFrame:CGRectMake(100, i*100, 80, 80)];
    v.backgroundColor = [UIColor redColor];
    [self.view addSubview:v];
}

2.GCD:GrandCentralDispatch 由C语言通过Block实现 效率高 有线程队列的概念
线程队列分为 串行队列 和并行队列

#import "ViewController.h"

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    //创建串行 线程对列
//    NSLog(@"a");
//    dispatch_queue_t myQueue = dispatch_queue_create("myQueue", 0);
//    dispatch_async(myQueue, ^{
//        for (NSInteger i = 0; i<3; i++) {
//            [NSThread sleepForTimeInterval:5];
//            NSLog(@"x-%ld",i);
//        }
//    });
//    dispatch_async(myQueue, ^{
//        for (NSInteger i = 0; i<3; i++) {
//            [NSThread sleepForTimeInterval:5];
//            NSLog(@"y-%ld",i);
//        }
//    });
//    NSLog(@"b");
    //获取系统提供的并行队列
    dispatch_queue_t myQueue =dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_async(myQueue, ^{
            for (NSInteger i = 0; i<3; i++) {
                [NSThread sleepForTimeInterval:5];
                NSLog(@"x-%ld",i);
                //回到主线程修改页面
                dispatch_async(dispatch_get_main_queue(), ^{
                    UIView *v = [[UIView alloc]initWithFrame:CGRectMake(100, i*100, 50, 50)];
                    v.backgroundColor = [UIColor redColor];
                    [self.view addSubview:v];
                });
            }
        });
        dispatch_async(myQueue, ^{
            for (NSInteger i = 0; i<3; i++) {
                [NSThread sleepForTimeInterval:5];
                NSLog(@"y-%ld",i);
            }
        });
}

示例打地鼠
Mouse.h

#import <UIKit/UIKit.h>

NS_ASSUME_NONNULL_BEGIN
@protocol MouseDelegate <NSObject>

-(void)successAction;
-(void)failAction;

@end
@interface Mouse : UIButton
@property(nonatomic,weak)id<MouseDelegate>delegate;
@end

Mouse.m

#import "Mouse.h"

@implementation Mouse
-(instancetype)initWithFrame:(CGRect)frame{
    self = [super initWithFrame:frame];
    if(self){
        self.backgroundColor = [UIColor redColor];
        [self addTarget:self action:@selector(clicked) forControlEvents:UIControlEventTouchUpInside];
        [self setTitle:@"3" forState:UIControlStateNormal];
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
            for (NSInteger i = 0; i<3; i++) {
                [NSThread sleepForTimeInterval:.5];
                //回到主线程
                dispatch_async(dispatch_get_main_queue(), ^{
                    
                    if(self.superview)//判断地鼠是否被删除了 如果删除了就不再修改title
                    {
                        int time = [[self titleForState:UIControlStateNormal] intValue] - 1;
                        [self setTitle:@(time).stringValue forState:UIControlStateNormal];
                        if(time == 0){
                            [self removeFromSuperview];
                            //失败次数+1
                            [self.delegate failAction];
                        }
                    }
                 
                });
            }
        });
//        [NSThread detachNewThreadWithBlock:^{
//
//        }];
    }
    return self;
}

-(void)clicked{
    [self removeFromSuperview];
    //成功次数+1
    [self.delegate successAction];

ViewController.m

#import "ViewController.h"
#import "Mouse.h"

@interface ViewController ()<MouseDelegate>
@property (weak, nonatomic) IBOutlet UILabel *successLabel;
@property (weak, nonatomic) IBOutlet UILabel *failLabel;

@end

@implementation ViewController
-(void)successAction{
    self.successLabel.text = @(self.successLabel.text.integerValue+1).stringValue;
}
-(void)failAction{
    self.failLabel.text = @(self.failLabel.text.integerValue+1).stringValue;
}
- (void)viewDidLoad {
    [super viewDidLoad];
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0) , ^{
        while (YES) {
            [NSThread sleepForTimeInterval:0.8];
            //回到主线程
            dispatch_async(dispatch_get_main_queue(), ^{
                Mouse *m = [[Mouse alloc]initWithFrame:CGRectMake(arc4random()%355, arc4random()%876, 20, 20)];
                m.delegate = self;
                [self.view addSubview:m];
            });
        }
    });
//    [NSThread detachNewThreadWithBlock:^{
//    }];
}
//-(void)addMouse{
//    Mouse *m = [[Mouse alloc]initWithFrame:CGRectMake(arc4random()%355, arc4random()%876, 20, 20)];
//    m.delegate = self;
//    [self.view addSubview:m];
//}

屏幕效果


image.png

3.NSOperation 更灵活 可以设置并行数量 和 线程之间的关系

  • 示例加载图片

TableViewController.m

#import "TableViewController.h"

@interface TableViewController ()
@property(nonatomic,strong)NSOperationQueue *myQueue;
@end

@implementation TableViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    self.myQueue = [NSOperationQueue new];
    self.myQueue.maxConcurrentOperationCount = 2;
}

#pragma mark - Table view data source


- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {

    return 100;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell" forIndexPath:indexPath];
    cell.textLabel.text = @(indexPath.row).stringValue;
    cell.imageView.image = nil;
    //通过NSOperation实现图片异步加载
    NSBlockOperation *op = [NSBlockOperation blockOperationWithBlock:^{
        UIImage *image = [self downloadImage];
        //通过GCD回到主线程
        dispatch_async(dispatch_get_main_queue(), ^{
            cell.imageView.image = image;
            //刷新显示自身控件
            //[iv setNeedsDispaly];
            //重新显示子控件
           [cell setNeedsLayout];
        });
    }];
    [self.myQueue addOperation:op];
    //通过GCD实现图片异步加载
//    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
//        UIImage *image = [self downloadImage];
//        dispatch_async(dispatch_get_main_queue(), ^{
//            cell.imageView.image = image;
//            //刷新显示自身控件
//            //[iv setNeedsDispaly];
//            //重新显示子控件
//           [cell setNeedsLayout];
//        });
//    });
    return cell;
}
-(UIImage *)downloadImage{
    [NSThread sleepForTimeInterval:.5];
    return [UIImage imageNamed:@"timg.jpg"];
}
  • 4.线程安全问题:当多条线程同时访问同一个数据的时候有可能会出现线程安全问题(示例卖票多线程通过同步代码块来解决的@synchronized (对象))
#import "ViewController.h"

@interface ViewController ()
@property(nonatomic)int totalCount;
@property(nonatomic)int selledCount;
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    self.totalCount = 100;
  
    NSThread *t1 = [[NSThread alloc]initWithTarget:self selector:@selector(sellAction) object:nil];
    t1.name = @"1号窗口";
    [t1 start];
    NSThread *t2 = [[NSThread alloc]initWithTarget:self selector:@selector(sellAction) object:nil];
    t2.name = @"2号窗口";
    [t2 start];
}
//
-(void)sellAction{
    while (self.selledCount<=100) {
        NSString *name = [NSThread currentThread].name;
        @synchronized (self) {
            NSLog(@"%@开始卖%d号票",name,self.selledCount+1);
            [NSThread sleepForTimeInterval:.5];
            self.selledCount++;
            
            NSLog(@"%@卖掉了%d号票还剩%d张",name,self.selledCount,self.totalCount -self.selledCount);
        }
      
    }
}

相关文章

网友评论

      本文标题:iOS多线程

      本文链接:https://www.haomeiwen.com/subject/porewktx.html