美文网首页
iOS 多线程 pthread & NSthread

iOS 多线程 pthread & NSthread

作者: 青椒辣不辣 | 来源:发表于2020-12-10 13:44 被阅读0次

pthread

#import <pthread/pthread.h>

NSString *string = @"pthread";
pthread_t thread;
/**
     参数一: 线程对象 传地址
     参数二: 线程的属性 (名称\优先级) 可赋值NULL
     参数三: 指向函数的指针
     参数四: 函数需要接受的字符串参数,可以不传递 可赋值NULL
     */
pthread_create(&thread, NULL, task, (__bridge void *)(string));

void *task (void *param){
    NSLog(@"%@---%s---%@",[NSThread currentThread],__func__,param);
    //打印结果:{number = 2, name = (null)}---task---pthread
    for (NSInteger i =0; i<10000; i++) {
        NSLog(@"%zd---%@",i,[NSThread currentThread]);
        //打印结果:{number = 2, name = (null)}
        if (i == 100) {
            pthread_exit(NULL); //退出线程
        }
    }
    return NULL;
}

NSthread

  • 创建线程的四种方法 alloc initwith..|detachNewThread|performSelectorInBack..|自定义
  • 设置线程的属性(名称&优先级[0.0~1.0])( 默认优先级是0.5 最高的优先级是1.0)
  • 方法执行完 自动释放
// 1.创建线程,并手动开启
-(void)newThread1{
    NSThread *threadA = [[NSThread alloc]initWithTarget:self selector:@selector(run:) object:@"创建线程的第一种方式--线程A"];
    [threadA setName:@"线程A"];
    [threadA setThreadPriority:1.0];//priority:优先 优先权
    [threadA start];
}
// 2.分离出一条子线程 自动开启线程的执行
-(void)newThread2{
    [NSThread detachNewThreadSelector:@selector(task) toTarget:self withObject:nil];
}
// 3.开启一条后台线程 自动开启线程的执行
-(void)newThread3{
    [self performSelectorInBackground:@selector(task) withObject:nil];
}
// 4.需要自定义NSThread类重写内部的方法实现(重写main)
-(void)newThread4{
    //1.创建线程对象
    RJThread *thread = [[RJThread alloc]init];
    //2.开始
    [thread start];
    
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(4 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        //4秒过后取消线程
        [thread cancel];
    });
}
-(void)task{
    for (NSInteger i = 0; i<1000; i++) {
        NSLog(@"%zd--%@",i,[NSThread currentThread].name);
        if (i == 50) {
            //[NSThread exit]; //强制退出线程
            //return;          // 任务执行完毕正常退出
            //continue;        // 进入下一个循环
            break;             // 跳出循环往下执行
        }
    }
    //NSLog(@"task---%@",[NSThread currentThread]);
    NSLog(@"start----");
    //阻塞线程(当前的线程)
    [NSThread sleepForTimeInterval:2.0]; //阻塞2秒
    [NSThread sleepUntilDate:[NSDate dateWithTimeIntervalSinceNow:3.0]];//阻塞3秒
    NSLog(@"%@",[NSDate distantFuture]);// 4001-01-01 00:00:00 +0000
    NSLog(@"%@",[NSDate distantPast]);//0000-12-30 00:00:00 +0000
    NSLog(@"end----");

}
-(void)run:(NSString *)string{
    NSLog(@"run--%@--%@",[NSThread currentThread].name,string);
    //run--线程A--创建线程的第一种方式--线程A
}
#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN

@interface RJThread : NSThread

@end

NS_ASSUME_NONNULL_END
----------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------
#import "RJThread.h"

@implementation RJThread
-(void)main{
    NSLog(@"starting thread.......");
    NSTimer *timer = [NSTimer timerWithTimeInterval:1 target:self selector:@selector(doTimerTask) userInfo:nil repeats:YES];
    [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];
    //如果当前线程不被取消,则进入循环
    while (!self.isCancelled) {
        [self doOtherTask];
        //如果在doTimerTask中,没有停止RunLoop的操作的话,RunLoop 一直在运行,下面这行代码 永远不会有返回值
        //runloop开始执行
        BOOL ret = [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
        NSLog(@"after runloop counting.........: %d", ret);
    }

    NSLog(@"finishing thread.........");
}
- (void)doTimerTask{
    NSLog(@"do timer task");
    // 添加RunLoop停止代码,使NSRunLoop 的runMode:(NSString *)mode beforeDate:(NSDate *)limitDate方法返回
    // 停止代码必须在runloop运行接口为runMode:下才能用
    // 这行代码写在 timer的触发事件中
    CFRunLoopStop(CFRunLoopGetCurrent());
}
- (void)doOtherTask{
    NSLog(@"do other task");
}
-(void)dealloc{
    NSLog(@"%s",__func__);
}
@end

\color{rgb(0 ,0, 205)}{线程间通信}

-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
    [NSThread detachNewThreadSelector:@selector(download) toTarget:self withObject:nil];;
}
-(void)download{
    NSURL *url = [NSURL URLWithString:@"https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1607584191107&di=dabaca87bbdb1c938cebc378ccd85480&imgtype=0&src=http%3A%2F%2Fattachments.gfan.com%2Fforum%2Fattachments2%2F201306%2F06%2F144906n0nffsz8h43i1t23.jpg"];
    NSData *imageData = [NSData dataWithContentsOfURL:url];
    UIImage *image = [UIImage imageWithData:imageData];
    //4.回到主线程设置图片
    //方法1
    //第三个参数:要不要等待调用方法结束之后再继续往下走
    //当为yes的时候,先让主线程运行showImage中的一些操作,之后再进行当前线程中的操作。
    //当为no的时候,先进行当前线程中的操作,之后让主线程运行showImage中的一些操作。
    [self performSelectorOnMainThread:@selector(showImage:) withObject:image waitUntilDone:NO];
    //方法2
    [self performSelector:@selector(showImage:) onThread:[NSThread mainThread] withObject:image waitUntilDone:NO];
    //方法3
    [self.imageView  performSelectorOnMainThread:@selector(setImage:) withObject:image waitUntilDone:YES];
}
-(void)showImage:(UIImage *)image{
    self.imageView.image = image;
    NSLog(@"UI----%@",[NSThread currentThread]);
}

\color{rgb(0 ,0, 205)}{计算代码执行的时间}

    //方法一
    NSDate *start  = [NSDate date]; //得到的是程序执行到此处的时间
    NSDate *end    = [NSDate date]; //得到的是程序执行到此处的时间
    NSLog(@"%f",[end timeIntervalSinceDate:start]);
    //方法二
    CFTimeInterval start = CFAbsoluteTimeGetCurrent();//获得的是绝对时间(参考00:00:00 1 January 2001)
    CFTimeInterval end   = CFAbsoluteTimeGetCurrent();
    NSLog(@"%f",end - start);

\color{rgb(0 ,0, 205)}{线程安全}@synchronized

//  假设一共8张票
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
    for (int i = 0; i < 10; i ++) {
        [NSThread detachNewThreadSelector:@selector(saleTicket:) toTarget:self withObject:[NSString stringWithFormat:@"%d",i]];
        NSLog(@"============%@",[NSString stringWithFormat:@"%d",i]);
    }
}
-(void)saleTicket:(NSString *)string{
    /*
     同步锁格式:
     @synchronized(锁对象){锁住的代码}
     锁对象:
     1)需要设置一个全局唯一的对象,self
     2)锁对象本身是有状态,打开|关闭
     注意点:
     1)锁定一份代码只能使用同一把锁,
     2)加锁的时候要注意位置
     3)加锁有前提条件:只有当多个线程存在抢夺同一块资源的时候才需要加锁
     4)加锁是需要耗费性能的
     5)造成线程同步(多个线程按照固定的顺序来执行任务)
     */
    NSLog(@"----------%@",string);
    @synchronized(self) {
        NSLog(@"++++++++++%@",string);
        NSInteger count = self.totalCount;
        if (count >0) {
            for (NSInteger i = 0; i<100000; i++) {}//演示耗时操作
            self.totalCount = count - 1; //卖出去一张票
            NSLog(@"%@卖出去了一张票,还剩下%zd张票",[NSThread currentThread].name,self.totalCount);
        }else{
            NSLog(@"票已经卖光了,做灰机回去吧~");
        }
    }
}

============<NSThread: 0x6000034cc980>{number = 1, name = main}##0
============<NSThread: 0x6000034cc980>{number = 1, name = main}##1
============<NSThread: 0x6000034cc980>{number = 1, name = main}##2
============<NSThread: 0x6000034cc980>{number = 1, name = main}##3
============<NSThread: 0x6000034cc980>{number = 1, name = main}##4
============<NSThread: 0x6000034cc980>{number = 1, name = main}##5
----------<NSThread: 0x6000034a85c0>{number = 8, name = (null)}##0
============<NSThread: 0x6000034cc980>{number = 1, name = main}##6
============<NSThread: 0x6000034cc980>{number = 1, name = main}##7
============<NSThread: 0x6000034cc980>{number = 1, name = main}##8
============<NSThread: 0x6000034cc980>{number = 1, name = main}##9
----------<NSThread: 0x6000034a8940>{number = 10, name = (null)}##2
++++++++++<NSThread: 0x6000034a85c0>{number = 8, name = (null)}##0
----------<NSThread: 0x6000034a8700>{number = 11, name = (null)}##3
----------<NSThread: 0x6000034a8b80>{number = 13, name = (null)}##5
----------<NSThread: 0x6000034a8bc0>{number = 14, name = (null)}##6
----------<NSThread: 0x6000034a8c00>{number = 15, name = (null)}##7
----------<NSThread: 0x6000034a8c80>{number = 17, name = (null)}##9
----------<NSThread: 0x6000034a8980>{number = 9, name = (null)}##1
卖出去了一张票,还剩下7张票
----------<NSThread: 0x6000034a8b40>{number = 12, name = (null)}##4
++++++++++<NSThread: 0x6000034a8b40>{number = 12, name = (null)}##4
----------<NSThread: 0x6000034a8c40>{number = 16, name = (null)}##8
卖出去了一张票,还剩下6张票
++++++++++<NSThread: 0x6000034a8b80>{number = 13, name = (null)}##5
卖出去了一张票,还剩下5张票
++++++++++<NSThread: 0x6000034a8700>{number = 11, name = (null)}##3
卖出去了一张票,还剩下4张票
++++++++++<NSThread: 0x6000034a8c40>{number = 16, name = (null)}##8
卖出去了一张票,还剩下3张票
++++++++++<NSThread: 0x6000034a8980>{number = 9, name = (null)}##1
卖出去了一张票,还剩下2张票
++++++++++<NSThread: 0x6000034a8c80>{number = 17, name = (null)}##9
卖出去了一张票,还剩下1张票
++++++++++<NSThread: 0x6000034a8940>{number = 10, name = (null)}##2
卖出去了一张票,还剩下0张票
++++++++++<NSThread: 0x6000034a8c00>{number = 15, name = (null)}##7
票已经卖光了,做灰机回去吧~
++++++++++<NSThread: 0x6000034a8bc0>{number = 14, name = (null)}##6
票已经卖光了,做灰机回去吧~




如果去掉@synchronized锁  则结果如下:

============<NSThread: 0x60000092ca40>{number = 1, name = main}##0
============<NSThread: 0x60000092ca40>{number = 1, name = main}##1
----------<NSThread: 0x60000097b100>{number = 7, name = (null)}##0
++++++++++<NSThread: 0x60000097b100>{number = 7, name = (null)}##0
============<NSThread: 0x60000092ca40>{number = 1, name = main}##2
============<NSThread: 0x60000092ca40>{number = 1, name = main}##3
============<NSThread: 0x60000092ca40>{number = 1, name = main}##4
============<NSThread: 0x60000092ca40>{number = 1, name = main}##5
============<NSThread: 0x60000092ca40>{number = 1, name = main}##6
============<NSThread: 0x60000092ca40>{number = 1, name = main}##7
============<NSThread: 0x60000092ca40>{number = 1, name = main}##8
============<NSThread: 0x60000092ca40>{number = 1, name = main}##9
卖出去了一张票,还剩下7张票
----------<NSThread: 0x600000978b00>{number = 8, name = (null)}##1
++++++++++<NSThread: 0x600000978b00>{number = 8, name = (null)}##1
----------<NSThread: 0x600000978740>{number = 9, name = (null)}##2
++++++++++<NSThread: 0x600000978740>{number = 9, name = (null)}##2
卖出去了一张票,还剩下6张票
----------<NSThread: 0x60000097a880>{number = 10, name = (null)}##3
++++++++++<NSThread: 0x60000097a880>{number = 10, name = (null)}##3
卖出去了一张票,还剩下6张票
----------<NSThread: 0x60000097b940>{number = 11, name = (null)}##4
++++++++++<NSThread: 0x60000097b940>{number = 11, name = (null)}##4
----------<NSThread: 0x60000097b9c0>{number = 13, name = (null)}##6
++++++++++<NSThread: 0x60000097b9c0>{number = 13, name = (null)}##6
----------<NSThread: 0x60000097ba00>{number = 14, name = (null)}##7
++++++++++<NSThread: 0x60000097ba00>{number = 14, name = (null)}##7
----------<NSThread: 0x60000097ba80>{number = 16, name = (null)}##9
++++++++++<NSThread: 0x60000097ba80>{number = 16, name = (null)}##9
卖出去了一张票,还剩下5张票
卖出去了一张票,还剩下5张票
卖出去了一张票,还剩下5张票
----------<NSThread: 0x60000097b980>{number = 12, name = (null)}##5
++++++++++<NSThread: 0x60000097b980>{number = 12, name = (null)}##5
卖出去了一张票,还剩下4张票
卖出去了一张票,还剩下5张票
----------<NSThread: 0x60000097ba40>{number = 15, name = (null)}##8
++++++++++<NSThread: 0x60000097ba40>{number = 15, name = (null)}##8
卖出去了一张票,还剩下4张票
卖出去了一张票,还剩下3张票



相关文章

  • OC_NSThread

    原文链接:iOS多线程--彻底学会多线程之『pthread、NSThread』 **NSThread **是苹果官...

  • 多线程(2)——NSThread

    iOS中实现多线程的四种方案 pthread NSThread GCD NSOpreation Pthread:这...

  • iOS多线程.md

    2018-05-22 iOS多线程-概念iOS多线程:『pthread、NSThread』详尽总结 多线程-概念图...

  • iOS多线程

    iOS中常用的多线程:pthread:C语言 NSThread:OC GCD:C NSOpreration:...

  • 多线程、Runloop、Runtime

    多线程 iOS多线程技术有哪几种方式pthread、NSThread、GCD、NSOperation 1. NSO...

  • iOS多线程

    iOS中常见的多线程方案 pthread NSThread GCD NSOperation GCD GCD执行任务...

  • NSOperation学习

    iOS的多线程技术主要有:pthread、NSThread、NSOperation、GCD。怎么选呢?pthrea...

  • iOS底层原理(四):多线程

    一、GCD iOS中常见的多线程方案有:pthread、NSThread、GCD、NSOperation,我们用的...

  • 底层原理:多线程

    iOS中常见多线程方案 NSThread 、 GCD 和 NSOperation 底层都是依赖于 pthread ...

  • IOS---多线程实现方案一 (pthread、NSThrea

    IOS多线程实现方案一 (pthread、NSThread) 在iOS开发中,多线程是我们在开发中经常使用的一门技...

网友评论

      本文标题:iOS 多线程 pthread & NSthread

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