iOS多线程编程NSThead

线程和进程

进程就是一个独立的应用程序,是cpu调度的独立单元,享有独立的系统资源(内存)
线程是进程中的执行单元,是cpu调用的最小单位,一个进程可以有多个线程但至少有一个,它们中有一个为主线程,其他为分线程

多线程编程

在我们编写程序时,有的任务会花取大量时间进行处理,所以我们为了防止这些任务阻塞到我们的主线程,造成UI卡顿,会用到多线程编程。
多个线程可以同时执行的,提高完成任务效率。

iOS中多线程编程主要有三种方式

  • NSThread:
  • NSOperation && NSOperationQueue
  • GCD

NSThread

NSThread多任务处理时,程序员需要手动对线程的生周期进行管理,线程数量完全自己决定

开辟分线程的三个方法

  • 静态方法创建:
 //参数:1.分线程执行的函数 2.分线程方法的执行者 3.参数
 [NSThread detachNewThreadSelector:@selector(threadMethod1) toTarget:self withObject:nil];
  • 使用alloc init方式创建线程 需要启动线程
 NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(threadMethod2) object:nil];
thread.name = @"分线程";
    // 启动线程
[thread start];
  • 隐性开辟分线程
   // 在performSelector系列方法中 只有此方法可以开辟分线程
    [self performSelectorInBackground:@selector(threadMethod3) withObject:nil];

其他方法

    // 此方法指定的testMehtod是在主线程中执行的
    [self performSelector:@selector(testMehtod)];
    // 退出线程 一般不使用
    [NSThread exit];
    //获取当前线程
    [NSThread currentThread]
    //判断是否是主线程
    [NSThread isMainThread]
    //获取主线程
    [NSThread mainThread]
    // 让当前线程休眠10s
    [NSThread sleepForTimeInterval:10];

注意:在分线程中不能操作UI,需要回到主线程中操作UI

 // 参数:1.回到主线程执行的方法 2.参数 3.是否要锁住当前线程等待主线程方法执行完毕
    [self performSelectorOnMainThread:@selector(mainThreadMethod) withObject:nil waitUntilDone:NO];

同步与异步

同步:多个任务按顺序执行。
异步:多个任务同时执行。

用NSThread实现线程同步

场景:卖票时,如果有一张票了,两个任务同时买票,他们获取的票数都是剩余一张,并且他们同时点击买票。结果是他们都会买到票,但是真实的票数只有一张,这样就会造成数据的混乱。这种情况我们就需要线程同步。意思就是我们需要让他们一个一个的按顺序买票,不是同时买票。

解决方案

@property (nonatomic, strong) NSThread *threadA;
@property (nonatomic, strong) NSThread *threadB;
@property (nonatomic, assign) NSInteger ticketsCount;
// 线程锁
@property (nonatomic, strong) NSLock *lock;
- (void)viewDidLoad {
    [super viewDidLoad];

    // 创建线程锁
    self.lock = [NSLock new];
    self.ticketsCount = 10;
    //创建两个线程去买票
    self.threadA = [[NSThread alloc] initWithTarget:self selector:@selector(sellTickets) object:nil];
    self.threadA.name = @"售票员A";

    self.threadB = [[NSThread alloc] initWithTarget:self selector:@selector(sellTickets) object:nil];
    self.threadB.name = @"售票员B";
}
// 点一下 模拟同时开始卖票
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    [self.threadA start];
    [self.threadB start];
}
  • NSLock实现:在多任务时,多个线程同时访问一个对象,会锁住这个代码块,只有等到当前线程任务执行完毕,其他线程才能接着执行
```
#pragma mark - lock形式
- (void)sellTickets
{
//while模拟售票员一直在在卖票
    while (YES)   
        // 加锁和解锁一定要成对出现
        // 加锁
        //意思就是阻塞同时访问这块资源的其他线程,只有当当前线程访问完毕,下一个线程才能够接着访问,实现线程的同步,按顺序执行。
        [_lock lock];
        // 1.获取票数
        NSInteger count = self.ticketsCount;
        // 2.检查票数
        if (count > 0)
        {
            // 3.暂停一会分线程  0.002 (保证两个都获取到了总票数 模拟理论上的情况)
            [NSThread sleepForTimeInterval:1];
            // 4.票数等于检查票数减一
            self.ticketsCount = count - 1;
            // 解锁
            [_lock unlock];
        }
        else
        {
            //没票
            [NSThread exit];
        }
    }
}
  • @synchronized:和NSLock的功能一样,在多任务时,多个线程同时访问一个对象,会锁住这个代码块,只有等到当前线程任务执行完毕,其他线程才能接着执行
#pragma mark - @synchronized形式
- (void)sellTickets
{
    while (YES) {
        // self表示一把锁 多个资源共用一把锁
        // 括号内
        @synchronized (self) {
            // 1.获取票数
            NSInteger count = self.ticketsCount;
            // 2.检查票数
            if (count > 0)
            {
                // 3.暂停一会分线程  0.002 (保证两个都获取到了总票数 模拟理论上的情况)
                [NSThread sleepForTimeInterval:0.002];
                // 4.票数等于检查票数减一
                self.ticketsCount = count - 1;
                // 打印当前线程、以及剩余票数
                NSLog(@"%@_____%ld", [NSThread currentThread], self.ticketsCount);
            }
            else
            {
                //没票
                [NSThread exit];
            }   
        }   
    }
}
  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值