ios学习总结之NSThread

ios里面多线程有多种实现方案,下面先来了解一下NSThread,这个算是最基础的一个了。

首先看NSThread创建,NSThread的创建有三种方法,分别是:

-(void)threadCreate{

    NSLog(@"%s",__PRETTY_FUNCTION__);

    //1.

    NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(threadCreateFunc:) object:@"普通线程"];

    [thread start];

    //2.

    [NSThread detachNewThreadSelector:@selector(threadCreateFunc:) toTarget:self withObject:@"分离子线程"];

    //3.

    [self performSelectorInBackground:@selector(threadCreateFunc:) withObject:@"后台线程"];

}


-(void)threadCreateFunc:(NSString*)string{

    NSLog(@"test - %@ - %@", [NSThread currentThread],string);

}


三种方法比较:

方法一:

    优点:可以拿到线程对象,并设置相关属性

    缺点:需要手动启动线程

方法二和三:

    优点:代码简介

    缺点:无法拿到线程对象,并设置相关属性

如果需要设置线程属性,比较常用的属性就是线程的name和priority了,比如

-(void)threadPriority{

    NSLog(@"%s",__PRETTY_FUNCTION__);

    NSThread* threadA = [[NSThread alloc]initWithTarget:self selector:@selector(threadPriorityFunc:) object:@"子线程"];

    threadA.name = @"子线程A";

    

    

    NSThread* threadB =[[NSThread alloc]initWithTarget:self selector:@selector(threadPriorityFunc:) object:@"子线程"];

    threadB.name =@"子线程B";

    

    

    NSThread* threadC =[[NSThread alloc]initWithTarget:self selector:@selector(threadPriorityFunc:) object:@"子线程C"];

    threadC.name=@"子线程C";

    

    

    threadA.threadPriority = 0.1;

    threadB.threadPriority = 1.0;

    threadC.threadPriority = 0.5;

    [threadA start];

    [threadB start];

    [threadC start];

    

}


-(void)threadPriorityFunc:(NSString*)string{

    for(int i=0;i<100;i++){

        NSLog(@"%d - %@", i + 1, [NSThread currentThread].name);

    }

}


比如,创建三个线程:子线程A,子线程B,子线程C,并设置三个线程的优先级为0.1,1.0,0.5。程序运行后的效果如下:

18-05-01 15:56:49.258160+0800 ocLearner[5100:219761] 59 - 子线程C

2018-05-01 15:56:49.258790+0800 ocLearner[5100:219760] 93 - 子线程B

2018-05-01 15:56:49.258882+0800 ocLearner[5100:219761] 60 - 子线程C

2018-05-01 15:56:49.258475+0800 ocLearner[5100:219759] 31 - 子线程A

2018-05-01 15:56:49.259150+0800 ocLearner[5100:219760] 94 - 子线程B

2018-05-01 15:56:49.259252+0800 ocLearner[5100:219761] 61 - 子线程C

2018-05-01 15:56:49.260346+0800 ocLearner[5100:219760] 95 - 子线程B

2018-05-01 15:56:49.260924+0800 ocLearner[5100:219761] 62 - 子线程C

2018-05-01 15:56:49.261092+0800 ocLearner[5100:219760] 96 - 子线程B

2018-05-01 15:56:49.261141+0800 ocLearner[5100:219759] 32 - 子线程A

2018-05-01 15:56:49.261493+0800 ocLearner[5100:219761] 63 - 子线程C

2018-05-01 15:56:49.261636+0800 ocLearner[5100:219760] 97 - 子线程B

2018-05-01 15:56:49.262173+0800 ocLearner[5100:219760] 98 - 子线程B

2018-05-01 15:56:49.262780+0800 ocLearner[5100:219760] 99 - 子线程B

从打印的效果截图上看,明显B的次数最多,C次之,A最少

关于线程的状态,启动一个线程可以用

-(void)start;

这个就不多说了。

如果想暂停线程,可以用下面两个方法

+(void)sleepUntilDate:(NSDate*)date;

+(void)sleepForTimeInterval:(NSTimeInterval)ti;

强行停止线程:

+(void)exit;

下面直接贴代码吧:

double now1=[[NSDate date] timeIntervalSince1970];

    NSLog(@"%@ - now1:%f",[NSThread currentThread],now1);

    [NSThread sleepUntilDate:[NSDate dateWithTimeIntervalSinceNow:3.0]];

    double now2=[[NSDate date] timeIntervalSince1970];

    NSLog(@"%@ - now2:%f,interval from now1:%f",[NSThread currentThread],now2,now2-now1);

    [NSThread sleepForTimeInterval:3.0];

    double now3=[[NSDate date] timeIntervalSince1970];

    NSLog(@"%@ - now3:%f,interval from now2:%f",[NSThread currentThread],now3,now3-now2);

    

    for (int i = 0; i < 100; ++i) {

        NSLog(@"%d - %@", i, [NSThread currentThread]);

        if (i == 10) {

            [NSThread exit];

        }

    }

    

    NSLog(@"----end----");

运行以后的效果图:

<NSThread: 0x604000666cc0>{number = 3, name = (null)} - now1:1525360716.066638

2018-05-03 23:18:39.073311+0800 ocLearner[21985:585836] <NSThread: 0x604000666cc0>{number = 3, name = (null)} - now2:1525360719.073184,interval from now1:3.006546

2018-05-03 23:18:42.078887+0800 ocLearner[21985:585836] <NSThread: 0x604000666cc0>{number = 3, name = (null)} - now3:1525360722.078788,interval from now2:3.005604

2018-05-03 23:18:42.079323+0800 ocLearner[21985:585836] 0 - <NSThread: 0x604000666cc0>{number = 3, name = (null)}

2018-05-03 23:18:42.080153+0800 ocLearner[21985:585836] 1 - <NSThread: 0x604000666cc0>{number = 3, name = (null)}

2018-05-03 23:18:42.081480+0800 ocLearner[21985:585836] 2 - <NSThread: 0x604000666cc0>{number = 3, name = (null)}

2018-05-03 23:18:42.082837+0800 ocLearner[21985:585836] 3 - <NSThread: 0x604000666cc0>{number = 3, name = (null)}

2018-05-03 23:18:42.083649+0800 ocLearner[21985:585836] 4 - <NSThread: 0x604000666cc0>{number = 3, name = (null)}

2018-05-03 23:18:42.084172+0800 ocLearner[21985:585836] 5 - <NSThread: 0x604000666cc0>{number = 3, name = (null)}

2018-05-03 23:18:42.084891+0800 ocLearner[21985:585836] 6 - <NSThread: 0x604000666cc0>{number = 3, name = (null)}

2018-05-03 23:18:42.085270+0800 ocLearner[21985:585836] 7 - <NSThread: 0x604000666cc0>{number = 3, name = (null)}

2018-05-03 23:18:42.085622+0800 ocLearner[21985:585836] 8 - <NSThread: 0x604000666cc0>{number = 3, name = (null)}

2018-05-03 23:18:42.085831+0800 ocLearner[21985:585836] 9 - <NSThread: 0x604000666cc0>{number = 3, name = (null)}

2018-05-03 23:18:42.086067+0800 ocLearner[21985:585836] 10 - <NSThread: 0x604000666cc0>{number = 3, name = 

可以看到,exit会使线程强行退出的。

关于线程,还有一个可能用到的比较多,就是线程之间的通讯。一个比较常见的场景就是从网络下载完图片资源后需要更新到界面上去的时候。必须要在主线程里更新,不能够在下载线程中之间更新。还是直接上代码吧:

-(void)threadCommunication{

    NSLog(@"%s",__PRETTY_FUNCTION__);

    NSURL* url = [NSURL URLWithString:@"http://pic1.win4000.com/wallpaper/2/4fcec0bf0fb7f.jpg"];

    NSData* data = [NSData dataWithContentsOfURL:url];

    UIImage* image =[UIImage imageWithData:data];

    NSLog(@"download-%@",[NSThread currentThread]);

    //方法1

    [self performSelectorOnMainThread:@selector(showImage:) withObject:image waitUntilDone:YES];

    //方法2

    //[self performSelector:@selector(showImage:) onThread:[NSThread mainThread] withObject:image waitUntilDone:YES];

    //方法3

    //[self.imageView performSelectorOnMainThread:@selector(setImage:) withObject:image waitUntilDone:YES];

}


-(void)showImage:(UIImage*)image{

    self.imageView.image = image;

    NSLog(@"showImage - %@", [NSThread currentThread]);

}

由其他线程,切回主线程有下面三个方法:

//方法1

    [self performSelectorOnMainThread:@selector(showImage:) withObject:image waitUntilDone:YES];

    //方法2

    //[self performSelector:@selector(showImage:) onThread:[NSThread mainThread] withObject:image waitUntilDone:YES];

    //方法3

    //[self.imageView performSelectorOnMainThread:@selector(setImage:) withObject:image waitUntilDone:YES];

其中最后一个方法不需要再直接定义新函数了。比较简便。

好了。NSThread还是一个很轻量级的多线程。大多数重量级的多线程一般都是用GCD了。所以,这里也就简单介绍一下吧。不在详细说明了



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值