多线程-NSThread

NSThread

每个iOS应用程序都有个专门用来更新显示UI界面、处理用户触摸事件的主线程,因此不能将其他太耗时的操作放在主线程中执行,不然会造成主线程堵塞

创建一条线程
方式一 动态方法
    // 1.创建子线程
    /*
     Target: 子线程需要调用谁的方法
     selector: 被子线程调用的方法
     object: 调用方法时, 给方法传递的参数
     */
    // 注意: 如果线程正在执行, 那么系统会自动强引用NSThread  当线程中的任务执行完毕, 系统会自动释放线程, 对线程进行一次release操作
    NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(demo:) object:@"lnj"];
  
    //  给线程取名字
    thread.name = @"子线程1";
    // 设置线程的优先级, 取值范围0.0~1.0, 1.0是最高, 默认就是0.5
    // 注意点: 线程的优先级越高, 那么被CPU调度的可能性就越大  但是并不代表着, 优先级高的一定会先执行
   
    thread.threadPriority = 0.0;
    // 2.启动线程    如果通过alloc/init创建NSThread, 那么需要手动启动线程
    [thread start];
方式二 静态方法
/*
     优点:
     - 使用简便
     - 如果通过detach方法创建线程, 不需要手动调用start启动线程 \ 系统会自动启动
     缺点:
     - 不可以进行其它设置
     应用场景:
     - 如果仅仅需要简单的开启一个子线程执行一些操作, 不需要对子线程进行其它设置, 那么推荐使用detach方法创建线程
     */
    [NSThread detachNewThreadSelector:@selector(demo:) toTarget:self withObject:@"canshu"];
方式三 隐式创建线程
  // 系统会自动在后台给我们开启一个子线程, 并且会自动启动该线程执行任务
    [self performSelectorInBackground:@selector(demo:) withObject:@"oooo"];

线程通信

场景:从网络下载一张图片,然后返回主线程更新UI

开启一个子线程下载图片

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

实现下载图片方法

- (void)downlod
{
    NSLog(@"%@", [NSThread currentThread]);  //   打印当前线程
    // 1.下载图片
     NSURL *url = [NSURL URLWithString:@"http://pic.4j4j.cn/upload/pic/20130531/07ed5ea485.jpg"];
     NSData *data = [NSData dataWithContentsOfURL:url];
    // 2.将二进制转换为图片
    UIImage *image = [UIImage imageWithData:data];  
}

拿到图片后 返回主线程更新UI 方式一

     /*
     waitUntilDone: 
     YES: 如果传入YES, 那么会等待updateImage方法执行完毕, 才会继续执行后面的代码
     NO:  如果传入NO, 那么不会等待updateImage方法执行完毕, 就可以继续之后后面的代码
     */
    // 可以在指定的线程中, 调用指定对象的指定方法
    [self performSelector:@selector(updateImage:) onThread:[NSThread mainThread] withObject:image waitUntilDone:YES];

拿到图片后 返回主线程更新UI 方式二 工作中常用

//  这个方法也就不需要再重新实现更新UI的方法了
 [self.imageView performSelectorOnMainThread:@selector(setImage:) withObject:image waitUntilDone:YES];

实现更新UI的方法

- (void)updateImage:(UIImage *)image
{
    NSLog(@"%@", [NSThread currentThread]);
    self.imageView.image = image;
}

在当前线程执行操作

[self performSelector:@selector(run) withObject:nil]; 

多条线程在同一时间访问同一块资源容易出现安全隐患

模拟场景:12306服务器设置了20张从北京到上海火车票,有三个售票员用他们的电脑进行售票,这里要需要用到互斥锁 它的作用就是锁住这块资源让它在同一时间只能让一条线程访问 接下来先测试加锁与不加锁的区别

创建3条线程代表3个售货员
- (void)viewDidLoad {
    [super viewDidLoad];
    // 0 初始化票数
    self.totalCount = 100;
    
    // 1 创建3个售票员
    NSThread *thread1 = [[NSThread alloc] initWithTarget:self selector:@selector(saleTicket) object:nil];
    thread1.name = @"售票员1";
    self.thread1 = thread1;
    NSThread *thread2 = [[NSThread alloc] initWithTarget:self selector:@selector(saleTicket) object:nil];
    thread2.name = @"售票员2";
    self.thread2 = thread2;
    NSThread *thread3 = [[NSThread alloc] initWithTarget:self selector:@selector(saleTicket) object:nil];
    thread3.name = @"售票员3";
    self.thread3 = thread3;
}
开始售票
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    // 2.让3个售票员同事售票
    [self.thread1 start];
    [self.thread2 start];
    [self.thread3 start];
}
售票进行中 不加锁
- (void)saleTicket
{
    while (1) {
        
        NSLog(@"欢迎光临");
            // 1.查询剩余的票数
            NSUInteger count = self.totalCount;
            // 2.判断是否还有余票
            if (count > 0) {
                // 线程1   让线程处于休眠状态   模拟售票时间为0.1秒
                [NSThread sleepForTimeInterval:0.1];
                // 2.1卖票
                self.totalCount = count - 1; // 99
                NSLog(@"%@卖了一张票, 还剩%zd票", [NSThread currentThread].name, self.totalCount);
            }else
            {
                // 3.提示客户, 没有票了
                NSLog(@"对不起, 没有票了");
                break;
            }
    }
    
}
看打印结果

明显线程没有获取到最新的值 造成数据访问错误


Paste_Image.png
售票进行中 加锁
// 售票方法
- (void)saleTicket
{
    while (1) {
        
        NSLog(@"欢迎光临");
        @synchronized (self) { //@synchronized  为互斥锁    self可以为任何对象  但必须是同一对象  保证单例
            
            // 1.查询剩余的票数
            NSUInteger count = self.totalCount;
            // 2.判断是否还有余票
            if (count > 0) {
                // 线程1   让线程处于休眠状态   模拟售票时间为0.1秒
                [NSThread sleepForTimeInterval:0.1];
                // 2.1卖票
                self.totalCount = count - 1; // 99
                NSLog(@"%@卖了一张票, 还剩%zd票", [NSThread currentThread].name, self.totalCount);
            }else
            {
                // 3.提示客户, 没有票了
                NSLog(@"对不起, 没有票了");
                break;
            }
        }

    }
    
}
这下就没有问题了
Paste_Image.png
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,734评论 6 505
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,931评论 3 394
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,133评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,532评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,585评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,462评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,262评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,153评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,587评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,792评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,919评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,635评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,237评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,855评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,983评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,048评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,864评论 2 354

推荐阅读更多精彩内容