IOS培训
美国上市IOS培训机构

400-111-8989

热门课程

IOS多线程的那些事

  • 时间:2015-07-27
  • 发布:佚名
  • 来源:达内

此文的目的,不是为了深度解析多线程,只是让大家看到一些多线程实现的内容,和基本定义。
也许很多人奇怪,多线程是为了干啥,简单来讲,一般是两个目的:1、最大化利用有限硬件资源,节约程序执行时间。例如:某个程序的逻辑,单个线程需要执行1小时,而且硬件资源的大部分都在闲置,所以我们就把闲置的资源调动起来,开辟多线程,使得执行时间小于1小时。
2、实现良好的 User Interface feeling。例如:我们在主线程执行 一个 一小时下载的时候,会发现,界面卡主了,不能动了。这样的程序自然会让人极其烦躁。利用多线程,就可以让下载在后台运行,界面依然可以操作。

所以本人写得内容,主要是总结了多线程的几种定义,以及哪些定义可以不阻塞主线程,哪些时候任务是串行,哪些时候任务是并行。

附件代码,把主线程的执行,用移动图片来实现。因为帖子字数限制,只粘贴了部分代码。
@interface ViewController ()
@property (weak, nonatomic) IBOutlet UIImageView *imageView;
@property (nonatomic,assign) int showNumber;
@property (nonatomic,assign) int showOtherNumber;
@property (nonatomic,strong) NSLock* lock;
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
}

-(void) touchesBeganNSSet *)touches withEventUIEvent *)event
{
    UITouch* touch = [touches anyObject];
    CGPoint point = [touch locationInView:self.view];
   
    self.imageView.center = point;
}

-(void)touchesMovedNSSet *)touches withEventUIEvent *)event
{
    UITouch* touch = [touches anyObject];
    CGPoint point = [touch locationInView:self.view];
   
    self.imageView.center = point;
}
- (IBAction)btn_Pthread_Clickedid)sender {
   
    //1、创建 PThread 对象
    pthread_t myPthread;
    int error = pthread_create(&myPthread,NULL,task,NULL);
   
    if(error != 0)
    {
        NSLog(@"创建错误!~");
    }
    else
    {
        NSLog(@"线程完成");
    }
   
}

void* task(void* data)
{
    //循环打印10次,每次睡眠1秒钟。
    //当控制器开始打印的时候,我们可以尝试,是否可以移动图片
    for (int i = 0; i < 10 ; i++) {
        [NSThread sleepForTimeInterval:1];
        NSLog(@"%d,%@",i+1,[NSThread currentThread]);
    }
   
    //在打印的过程中,我们发现,图片可以移动,而且通过打印信息可以知道打印是由 非主线程执行的。
    //那么PThread 创建的线程,是异步执行的。
    //异步和同步的区别,我们后面GCD在详细讲
   
    return 0;
   
}

- (IBAction)btn_Thread1_Clickedid)sender {
   
    //创建NSThread对象
    NSThread* thread = [[NSThread alloc]initWithTarget:self selectorselector(task) object:nil];
   
    //这种方法可以设置thread 的其他属性,例如 优先级,size等。
    //[thread setThreadPriority:0.8]; 0-1.0
    //thread.stackSize = 16 * 1024;
   
    [thread start];
   
    //结论 子线程执行的时候,图片依然可以移动,那么表示子线程没有阻塞主线程。是异步执行
}

-(void) task
{
    //循环打印10次,每次睡眠1秒钟。
    //当控制器开始打印的时候,我们可以尝试,是否可以移动图片
    for (int i = 0; i < 10 ; i++) {
        [NSThread sleepForTimeInterval:1];
        NSLog(@"%d,%@",i+1,[NSThread currentThread]);
    }
}

- (IBAction)btn_Thread2_Clickedid)sender {
    //创建NSThread 对象并执行
    [NSThread detachNewThreadSelectorselector(task) toTarget:self withObject:nil];
   
    //结论 子线程执行的时候,图片依然可以移动,那么表示子线程没有阻塞主线程。是异步执行
}

- (IBAction)btn_Thread3_Clikedid)sender {
   
    //后台执行task
    [self performSelectorInBackgroundselector(task) withObject:nil];
   
    //从打印以及 可以移动图片可知,此方法后台创建了子线程,而且是异步执行。
}

- (IBAction)btn_ThreadAndLock_Clickedid)sender {
   
    //在此我们先查看一个事例,如果不加锁,两个并行异步的线程访问到同一个资源时候,可能会导致脏数据(请百度)产生。
   
    //在此之前我们定义一个属性 int showNumber;
    //初始化showNumber 为0;
//    self.showNumber = 0;
//   
//    NSThread* firstThread = [[NSThread alloc]initWithTarget:self selectorselector(task2) object:nil];
//   
//    NSThread* secondThread = [[NSThread alloc]initWithTarget:self selectorselector(task2) object:nil];
//   
//    [firstThread start];
//    [secondThread start];
   
   
   
    //执行下列代码,请把 first 和 second 的内容注释。
   
     //初始化Lock
     self.lock = [[NSLock alloc]init];
     
     //初始化showOtherNumber
     self.showOtherNumber = 0;
     
     NSThread* thirdThread = [[NSThread alloc]initWithTarget:self selectorselector(task3) object:nil];
     
     NSThread* forthThread = [[NSThread alloc]initWithTarget:self selectorselector(task3) object:nil];
     
     [thirdThread start];
     [forthThread start]
}
-(void) task2
{
    //偏移showNumber ,如果showNumber = 0 就 + 1,如果showNumber = 1 就 - 1; 如果正偏移量超过 1,就结束。
   
    while (1) {
        
        if(self.showNumber == 0)
        {
            NSLog(@"%@ ---> %d",[NSThread currentThread],++self.showNumber);
        }
        else if(self.showNumber == 1)
        {
            NSLog(@"%@ ---> %d",[NSThread currentThread],--self.showNumber);
        }
        else
        {
            NSLog(@"%@ ---> %d",[NSThread currentThread],self.showNumber);
            return;
        }
    }
   
    //我们参照逻辑,showNumber初始值是 0,那么在执行++操作后,showNumber的下一次执行就是 --,按照逻辑,showNumber永远在0,1之间徘徊,而且打印的结果应该是 0,1的交叉顺序重复
   
    //但是在运行后,我们发现终于发生了可怕的事情,showNumber 居然 变成了2,一个我们意料之外的值。 那么可见在两条线程同时执行task2的时候,产生了脏数据 2。 如果线程更多,这个错误可能会更大。
   
    //现实生活中很多例子不允许我们有这样的结果,例如春节买火车票,买电影票,甚至是银行的存款,我们绝对不能允许这些脏数据的存在,因为它不可预料。 所以请参见下一个task3,加锁之后的结果。
}

@end
上一篇:为梦想扬帆起航!
下一篇:几种常用的获取自定义TableViewCell

9月份---iOS训练营课程安排

达内推出五大精品课程,推动IT培训进入培优时代

达内学员跨专业入职欧洲知名软件企业

ios培训哪家好 高薪就业数达内

选择城市和中心
贵州省

广西省

海南省