UI多线程、开辟方式及线程安全

来源:互联网 发布:足彩数据分析下载 编辑:程序博客网 时间:2024/05/19 19:40

1.多线程的简介

进程:
是操作系统的基础,是一次程序的执行,是操作系统动态执行的基本单元,
在传统的操作系统中,进程是基本的分配单元,也是基本执行单元。
线程:
有时被称为轻量进程,是进程执行流中的最小单元;

iOS程序中默认只有一个线程,也就是主线程,所有的用户交互、界面刷新都必须在主线程中进行
若再主线程中执行复杂长时间的操作,会阻塞主线程(程序无响应等),大大降低用户体验;可以通过开启后台线程来执行这些操作,保持主线程流畅,避免这类问题的发生。

在主线程中调方法可能会堵塞主线程,因此开辟子线程可以避免此类现象。
一般不会去开辟多线程 如异步网络请求  它会会自动开辟线程去完成 不用专门去开辟
2.
线程开辟方式代码示例:

方法一://NSObject的类目

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

    //后台调用某个方法

    //打印1-99 和打印@“打印完毕同时进行 完成之后交给主线程与界面进行交互(谁先完成就先给主线程交互)


方法二:NSThread  线程方法//类方法

    [NSThread detachNewThreadSelector:@selector(logOneToHundred) toTarget:self withObject:nil];


方法三:NSThread  线程方法//示例方法

    NSThread * thread = [[NSThread alloc]initWithTarget:self selector:@selector(getImageWithUrl) object:nil];

    [thread start];


方法四:NSOperationQueue 队列方法(用于多网络请求管理) NSOperation 类似于UIController

第一步:初始化队列 

//初始化操作队列--block方法执行

    _operationQueue = [[NSOperationQueue allocinit];

第二步:用block方法调用方法

  NSOperation * blockOperation = [NSBlockOperation blockOperationWithBlock:^{

        //这个Block中写入 开辟线程用 来做什么的

        [self getImageWithUrl];

    }];

    [blockOperation setCompletionBlock:^{

        //这个block中写入 线程执行完毕后 的操作。。。

        [self performSelectorOnMainThread:@selector(updateUI) withObject:nil waitUntilDone:NO];

    }];

第三步:将block方法放入声明的队列中

    //注意NSOperation的子类实例对象必须放到操作队列中执行

    [_operationQueue addOperation:blockOperation];


方法五:NSOperationQueue 队列方法(用于多网络请求管理)NSOperation子类的方法

第一步:声明子类对象,调用方法 

   NSInvocationOperation * invocationOperation = [[NSInvocationOperation allocinitWithTarget:self selector:@selector(getImageWithUrl) object:nil];

第二步:用block方法调方法

    [invocationOperation setCompletionBlock:^{

        [self performSelectorOnMainThread:@selector(updateUI) withObject:nil waitUntilDone:NO];

    }];

第三步:将block方法放入声明的队列中

    [_operationQueue addOperation:invocationOperation];


法五:自定义NSOperation子类方法

第一步:创建一个继承于NSOperation的自定义类 command + N  .h文件中

#import <Foundation/Foundation.h>


@interface CustomOperation : NSOperation


- (void)main;//重写耗时较长的方法


@end


第二步:重写main方法  .m文件中

#import "CustomOperation.h"


@implementation CustomOperation


- (void)main{//重写耗时较长的方法

        //当前线程耗时三秒的操作

    [NSThread sleepForTimeInterval:3];

}

@end


第三步:声明子类对象,调用方法

    CustomOperation * customOperation = [[CustomOperation allocinit];


第四步:用block方法调方法

    [customOperation setCompletionBlock:^{

        [self performSelectorOnMainThread:@selector(updateLableWithString:) withObject:@"123"waitUntilDone:NO];

    }];


第五步:将block方法放入声明的队列中

    [_operationQueue addOperation:customOperation];


法六:GCD方法

    //创建一个并行队列

    dispatch_queue_t globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT0);

    //异步执行队列

    dispatch_async(globalQueue, ^{

        //开辟的线程用来干什么。。。

        [self getImageWithUrl];


        //执行一个主队列

        dispatch_async(dispatch_get_main_queue(), ^{

            //刷新界面

            [self performSelectorOnMainThread:@selector(updateUI) withObject:nil waitUntilDone:NO];

        });

    });

3.线程安全—线程锁
当多个线程同时访问一个资源时,会出现线程安全(数据、变量)问题:
UIKit中的所有对象默认都是非线程安全的、需要在主线程刷新UI界面元素

iOS中保证变量线程安全的方法:
(1)atomic特性属性声明
(2)@synchronized关键字
(3)NSLock线程锁
代码示例:

第一步:在接口文件声明[全局变量或属性均可]
NSInteger _count;//验证线程安全

        NSLock * _lock;//线程锁

第二步:初始化线锁 

       _lock = [[NSLock alloc]init];//初始化

第三步:

    [NSThread detachNewThreadSelector:@selector(upCount) toTarget:self withObject:nil];

    [NSThread detachNewThreadSelector:@selector(downCount) toTarget:self withObject:nil];



- (void)upCount{

    

    while (1) {

//        //方法一:

//        //保护成员变量每次只能被一个线程访问

//        @synchronized(self){

//            NSLog(@"%ld", _count +=1);

//        }

        

        //方法二:

        [_lock lock];//上锁

        NSLog(@"%ld"_count +=1);

        [_lock unlock];//解锁

    }

}


- (void)downCount{

    

    while (1) {

//        //保护成员变量每次只能被一个线程访问

//        @synchronized(self){

//            NSLog(@"%ld", _count -=1);

//        }

        

        //方法二:

        [_lock lock];//上锁

        NSLog(@"%ld"_count -=1);

        [_lock unlock];//解锁

    }

}




0 0
原创粉丝点击