代码改变世界

多线程3

2015-10-16 04:36  真实16  阅读(144)  评论(0编辑  收藏  举报

//

//  ViewController.m

//  UI-NO.24多线程-1

//

//  Created by Bruce on 15/8/25.

//  Copyright (c) 2015年 Bruce. All rights reserved.

//

/*

 当用户下载资源、进行图像处理、耗时数据处理等任务时 往往希望操作这个任务的时候 其他的操作不会被中断 这时候 就用到了 多线程

 

 

 在单线程中一个线程只能执行一个任务,一个任务处理不完另一个任务就不能开始,这样会影响用户体验 让用户感觉APP卡顿

 

 

 现在苹果手机都是多核处理器,这样我们可以把一个任务分成多个步骤,在不要求顺序的情况下 使用多线程既能解决线程阻塞 增加用户体验又能充分利用多核处理器运行能力

 

 

 

 每个应程序的内部,存在一个或多个执行线程,它同时或在一个几乎同时执行不同的操作

 

 

 面试题:什么是进程?什么是线程?什么是多线程?

 进程与线程:每个系统运行的程序都是一个进程,每个进程里面包含了一到多个线程

 

 线程是一组指令的集合,程序中一个单一的顺序控制流程,是一个程序中,独立运行的程序片段(一个应用程序里面 单一的顺序控制执行的一个任务)

 

 

 程序运行后,系统会创建一个叫做(main)主线程的线程,所有的UI控件都必须运行在主线程中,所以有人也叫它UI线程

 

 

 如果将所有的任务都放在主线程中,容易造成UI阻塞

 

 

 多线程:在同一个应用程序内,同时运行多个线程,完成不同的工作,叫做多线程

 

 

 为什么要使用多线程:单线程的应用程序中,代码沿直线执行,只有前面的代码执行完了,才会去执行后面的代码,中间这段时间,实际上就处于等待状态。当用户执行某项操作,比如上传文件,或者下载文件,主线程会执行这个任务,直到上传结束后,主线程才能继续后面的工作,在这短时间内,主线程处于忙碌状态,不会对用户的请求做出任何反应,最直观的感受就是界面卡死,特别是操作这个任务需要大量的时间的时候就更为明显

 既然单一的一个线程不能满足我们的需求,那我们就可以使用今天要讲的多线程进行操作,在用户需要上传或者下载文件的时候,开辟一个独立的线程,专门负责这个任务,这样两个线程就会并行去工作,主线程也就不用花费这么久去等待去更新界面了

 当然,使用多线程有利有弊,多线程高效的背后是代码复杂程度的上升,需要管理线程之间的同步和互斥,需要协调线程间的通信,这就是我们常说的线程管理

 

 

 在iOS中每个进程启动后都会建立一个主线程(UI线程),在iOS中除了主线程,其他子线程是独立于Cocoa Touch的

 

 

 // iOS中有几种多线程方式

 iOS中有三种多线程策略供开发者使用:NSThread、NSOperation(基类不可以直接使用  只能使用他的子类)、GCD(Grand Central Dispatch)

//  GCD 苹果 推荐的一种 实现 多线程的方式

 

 

 

 // 轻量级 :对系统框架的依赖性的程度

 NSThread:是这三种策略里面相对轻量级的,需要自己去管理他的生命周期,以及线程之间的同步,线程共享同一应用程序的部分内存空间,他们拥有对数据相同的访问权限,所以得协调多个线程对同一数据的访问,常用的做法是在访问之前加锁,这会导致一定的性能开销

 

 

 NSThread的创建和启动:

 NSThread的创建主要有两种直接方式:

 init

 这种方式得手动去启动线程,虽然我们alloc init了 但是只有我们start的时候才会真正去创建去启动这个线程(这是一种延迟实现的思想)

 

 + (void)detachNewThreadSelector:(SEL)selector toTarget:(id)target withObject:(id)argument;

 这种创建线程的方式,会立即开辟一个线程并启动线程

 

 

 线程之间的通讯

 performSelectorOnMainThread withObject:waitUntilDone:

 更新主线程

 performSelector:onThread:withObject:waitUntilDone:

 更新指定子线程

 

 

 解决 阻塞 主线程

 */

#import "ViewController.h"

 

@interface ViewController ()

{

    UIImageView *pointView;

    

    NSThread *newThread;

    NSCondition *condition;

    int ticketNum;

    int count;

}

@end

 

@implementation ViewController

 

- (void)viewDidLoad {

    [super viewDidLoad];

    

    /*

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

     //    这种创建线程的方式,会立即开辟一个线程并启动线程

     NSLog(@"主线程");

     */

    

    /*

     newThread = [[NSThread alloc]initWithTarget:self selector:@selector(updata1) object:nil];

     [newThread start];

     NSLog(@"主线程");

     //    这种方式得手动去启动线程,虽然我们alloc init了 但是只有我们start的时候才会真正去创建去启动这个线程(这是一种延迟实现的思想)

     

     */

    /*

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

     NSLog(@"主线程");

     //    这是一种隐式创建线程的方法,效果与第一种一样

     */

    

    /*

     线程之间的通讯

     

     performSelectorOnMainThread withObject:waitUntilDone:

     更新主线程

     

     performSelector:onThread:withObject:waitUntilDone:

     更新指定子线程

     */

    

    //    线程同步  线程锁

    //    NSCondition

    /*

    ticketNum = 100;

    condition = [[NSCondition alloc]init];

    

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

    thread1.name = @"thread1";

    [thread1 start];

    

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

    thread2.name = @"thread2";

    [thread2 start];

    

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

    thread3.name = @"thread3";

    [thread3 start];

*/

    

    

    

    

    

//    ---------------------------------------------

    

    self.view.backgroundColor = [UIColor blackColor];

    

    pointView = [[UIImageView alloc]initWithFrame:CGRectMake(0, 0, 100, 100)];

    pointView.backgroundColor = [UIColor whiteColor];

    pointView.layer.cornerRadius = 50;

    pointView.layer.masksToBounds = YES;

    [self.view addSubview:pointView];

    

    UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(tap:)];

    [self.view addGestureRecognizer:tap];

    

    UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];

    button.frame = CGRectMake(10, 20, 100, 30);

    [button setTitle:@"下载图片" forState:UIControlStateNormal];

    [button addTarget:self action:@selector(loadData) forControlEvents:UIControlEventTouchUpInside];

    [self.view addSubview:button];

    

}

/*

- (void)act

{

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

    while (ticketNum >= 0) {

        

        [condition lock];

        if(ticketNum >= 0){

            [NSThread sleepForTimeInterval:0.1];

            count = 100 - ticketNum;

            NSLog(@"当前票数是:%d,售出:%d,线程名:%@",ticketNum,count,[NSThread currentThread].name);

            ticketNum--;

        }

        [condition unlock];

        

    }

}

- (void)updata

{

    sleep(10);

    NSLog(@"子线程");

}

 

- (void)updata1

{

    sleep(5);

    NSLog(@"newThread子线程");

    [self performSelector:@selector(yayaya) onThread:newThread withObject:nil waitUntilDone:YES];

}

- (void)yayaya

{

    NSLog(@"执行");

}

*/

//普通

- (void)loadData

{

    NSLog(@"...");

    sleep(3);

    NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:@"http://file.bmob.cn/M01/33/41/oYYBAFXcMhaARlGBAABOZfJ7P6Y062.png"]];

    pointView.image = [UIImage imageWithData:data];

}

 

/*

//多线程

- (void)loadData

{

    NSLog(@"...");

    

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

    

}

 

- (void)commentData

{

    sleep(3);

    NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:@"http://file.bmob.cn/M01/33/41/oYYBAFXcMhaARlGBAABOZfJ7P6Y062.png"]];

    pointView.image = [UIImage imageWithData:data];

}

*/

 

- (void)tap:(UITapGestureRecognizer *)sender

{

    

    pointView.center = [sender locationInView:self.view];

}

 

 

 

 

- (void)didReceiveMemoryWarning {

    [super didReceiveMemoryWarning];

    // Dispose of any resources that can be recreated.

}

 

@end