多线程——NSThread

 

什么是多线程?


一句话,对功能的实现的流程,一个流程就是一个线程。在一个程序运行时至少有一个线程在运行,这个线程就是主线程。单线程下,只有当前的功能执行完毕,才执行下一个功能,给用户最直观的感受就是程序静止不动了。多线程就能解决这样的问题,他的原理是,吧功能分化称若干某块,然后有系统为其分配若干个线程,这些线程之间互不干扰,并行运作。提高了用户的体验感受,更加合理的发挥了系统的资源利用率。可是,这样加大了我们对多个线程之间合理安排的难度,比如说多线程的传值问题,相应处理。这就是线程管理所属的范畴。
只有一个线程的程序是单线程程序,主线程负责程序的所有代码(UI的展示、刷新、网络请求、本地存储)。这些代码只能顺序执行,无法并发执行。主线程在程序启动的时被创建,用于执行Main 函数。
拥有多个线程的程序被称为多线程。IOS允许用户自己开辟新的线程,相对于主线程来说这些线程被称为是子线程。主线程和子线程是独立的
调整程序的时候,最好不要去破坏原有运行正常的代码。
并行就是多个指令在多个处理器上执行,并发就是同一时刻只有一条指令在执行,但是多个进程指令被快速轮换,使得在宏观上似乎是同时执行的效果。
单CPU多线程仅仅解决了流畅的问题,并没有真正的解决线程之间的阻塞等待,但是多线程就解决此问题,是并行的计算的。

最形象的比喻来阐明上述的概念:

你吃饭吃到一半,电话来了,你一直到吃完了以后才去接,这就说明你不支持并发也不支持并行。
你吃饭吃到一半,电话来了,你停了下来接了电话,接完后继续吃饭,这说明你支持并发。
你吃饭吃到一半,电话来了,你一边打电话一边吃饭,这说明你支持并行。

并发的关键是你有处理多个任务的能力,不一定要同时。
并行的关键是你有同时处理多个任务的能力。

所以我认为它们最关键的点就是:是否是『同时』。
 理解并行于并发的区别


线程的创建,并执行线程:

- (void)viewDidLoad
{
    [super viewDidLoad];
    for(int i = 0 ; i < 100 ; i++)
    {
        NSLog(@"===%@===%d" , [NSThread currentThread].name , i);
        if(i == 20)
        {
            // 创建线程对象
            NSThread *thread = [[NSThread alloc]initWithTarget:self
                selector:@selector(run) object:nil];
            // 启动新线程
            [thread start];
            // 创建并启动新线程
            [NSThread detachNewThreadSelector:@selector(run) toTarget:self
                withObject:nil];
        }
    }
}

- (void)run
{
    for(int i = 0 ; i < 100 ; i++)
    {
        NSLog(@"-----%@----%d" , [NSThread currentThread].name, i);
    }
}

线程的状态:

线程被创建启动后,他并不是一启动就进入执行状态、也不是一直处于 执行状态。一个启动的线程会处于待命状态,不可能一直霸占CPU资源,他会一直在待命——执行——待命——执行这样的循环着切换,至于何时切换则取决于系统的资源调度。只有被调度多线程才会处于执行状态。当线程对象启动 star 方法的时候,线程就处于待命状态,但是未必立即执行,要想提高执行速度中,让其立即执行,可以设定当主线程休眠0.001秒就是1毫秒的时候,立即运行子线程,使用方法为 NSThread.sleepForTimeINterval(0.001),这样主线程会在休眠1毫秒后立即执行子线程,这1毫秒内CPU在处理其他的事物并未闲置:

NSThread* thread;
- (void)viewDidLoad
{
    [super viewDidLoad];
    // 创建新线程对象
    thread = [[NSThread alloc] initWithTarget:self selector:@selector(run)
        object:nil];
    // 启动新线程
    [thread start];
}
- (void)run
{
    for(int i = 0 ; i < 100 ; i++)
    {
        if([NSThread currentThread].isCancelled)
        {
            // 终止当前正在执行的线程
            [NSThread exit];
        }
        NSLog(@"-----%@----%d" , [NSThread currentThread].name, i);
        // 每执行一次,线程暂停0.5秒
        [NSThread sleepForTimeInterval:0.5];
    }
}
- (IBAction)cancelThread:(id)sender
{
    // 取消thread线程,调用该方法后,thread的isCancelled方法将会返回NO
    [thread cancel]; 
}

使用多线程去下载图片如下:

- (IBAction)showImage:(id)sender
{
    NSString* url = @"https://ss0.bdstatic.com/5aV1bjqh_Q23odCf/static/superman/img/logo/bd_logo1_31bdc765.png";
    // 创建新线程对象
    NSThread *thread = [[NSThread alloc]initWithTarget:self
        selector:@selector(downloadImageFromURL:) object:url];
    // 启动线程
    [thread start];
}
// 定义一个方法作为线程执行体。
-(void)downloadImageFromURL:(NSString *) url
{
    // 从网络获取数据
    NSData *data = [[NSData alloc]
        initWithContentsOfURL:[NSURL URLWithString:url]];
    // 将网络数据初始化为UIImage对象
    UIImage *image = [[UIImage alloc]initWithData:data];
    if(image != nil)
    {
        // 在主线程中执行updateUI:方法
        [self performSelectorOnMainThread:@selector(updateUI:)
            withObject:image waitUntilDone:YES]; //
    }
    else
    {
        NSLog(@"---下载图片出现错误---");
    }
}
-(void)updateUI:(UIImage*) image
{
    self.iv.image = image;
}

取消线程如下:

NSThread* thread;
- (void)viewDidLoad
{
    [super viewDidLoad];
    // 创建新线程对象
    thread = [[NSThread alloc] initWithTarget:self selector:@selector(run)
        object:nil];
    // 启动新线程
    [thread start];
}
- (void)run
{
    for(int i = 0 ; i < 100 ; i++)
    {
        if([NSThread currentThread].isCancelled)
        {
            // 终止当前正在执行的线程
            [NSThread exit];
        }
        NSLog(@"-----%@----%d" , [NSThread currentThread].name, i);
        // 每执行一次,线程暂停0.5秒
        [NSThread sleepForTimeInterval:0.5];
    }
}
- (IBAction)cancelThread:(id)sender
{
    // 取消thread线程,调用该方法后,thread的isCancelled方法将会返回NO
    [thread cancel]; 
}

  待续。。。。

 



原文地址:https://www.cnblogs.com/benpaobadaniu/p/4853047.html