zoukankan      html  css  js  c++  java
  • iOS多线程的基本使用

    一、NSThread:

     

    程序就是一段代码,是静态的概念

     

     

    进程是运行起来的程序,是动态的概念,进程需要占内存空间

     

     

    线程是进程的基本单位,一个进程至少有一个线程,iOS程序默认有一个主线程,用来显示和操作UI,主线程由系统自动创建,有系统管理。如果主线程不能满足我们的需求,可以手动创建线程,手动创建的线程需要我们自己管理。

     

     

    1.例:让一个线程延迟10秒运行

     

    - (void)viewDidLoad {

        [superviewDidLoad];

        // Do any additional setup after loading the view, typically from a nib.

        

        //按钮一

        UIButton *btn1 = [MyUtilcreateBtnFrame:CGRectMake(100,10080,40title:@"按钮一"bgImageName:niltarget:selfaction:@selector(clickBtnOne:)];

        [self.viewaddSubview:btn1];

        

        //按钮二

        UIButton *btn2 = [MyUtilcreateBtnFrame:CGRectMake(100,20080,40title:@"按钮二"bgImageName:niltarget:selfaction:@selector(clickBtnTwo:)];

        [self.viewaddSubview:btn2];

    }

     

    - (void)clickBtnOne:(id)sender

    {

        //模拟耗时较长的操作

        //例如实际中的网络请求或者数据库的操作

        //让线程睡眠十秒

        [NSThreadsleepForTimeInterval:10];

        

        //如果不使用多线程,会有界面假死的现象

        //用户体验不好

        //所有在这种情况下我们需要使用多线程

    }

     

    - (void)clickBtnTwo:(id)sender

    {

        NSLog(@"%s",__func__);

    }

     


     

    2.线程的优先级:

     

    //用线程的这个属性来修改线程的优先级,属性值越大,执行的次数越多

     

       t1.threadPriority =0;

     

     

    - (void)viewDidLoad {

        [superviewDidLoad];

        // Do any additional setup after loading the view, typically from a nib.

        

        //线程一

        NSThread *t1 = [[NSThreadallocinitWithTarget:selfselector:@selector(threadOne)object:nil];

        //修改优先级

        //优先级的值在0-1之间,优先级越高,执行的次数相对来说会越多

        t1.threadPriority =0;

        [t1 start];

        

        //线程二

        NSThread *t2 = [[NSThreadallocinitWithTarget:selfselector:@selector(threadTwo)object:nil];

        //修改优先级,线和二大于线程一,线程二先执行完成

        t2.threadPriority =1;

        [t2 start];

    }

    - (void)threadOne

    {

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

            NSLog(@"线程一:%d", i);

        }

    }

    - (void)threadTwo

    {

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

            NSLog(@"线程二:%d", i);

        }

    }

     

     

    3. 线程锁:

    第一种方法用: @synchronized加线程锁

     

    -(void)withDraw:(float)money

    {

        //多个线程修改同一块资源的时候,会出现问题

        //我们需要用线程锁的方式解决

        

        @synchronized(self){

            

            if (_money >= money) {

                

                //模拟取钱的时间

                [NSThreadsleepForTimeInterval:1];

                

                _money -= money;

                NSLog(@"%@取了%f",[NSThreadcurrentThread].name,money);

                

            }else{

                NSLog(@"余额不足");

            }

        }

        

    }

     

    @end

     

     

     

    第二种方法:

    用NSLock 来实现加锁和解锁

     

     

    @implementation MyAccount

    {

        //线程锁

        NSLock *_myLock;

    }

     

    -(instancetype)init

    {

        if (self = [superinit]) {

            

            _myLock = [[NSLockallocinit];

        }

        returnself;

    }

     

    -(void)withDraw:(float)money

    {

        //多个线程修改同一块资源的时候,会出现问题

        //我们需要用线程锁的方式解决

        

        //加锁

        [_myLocklock];

        

        if (_money >= money) {

          

            //模拟取钱的时间

            [NSThreadsleepForTimeInterval:1];

            

            _money -= money;

            NSLog(@"%@取了%f",[NSThreadcurrentThread].name,money);

            

        }else{

            NSLog(@"余额不足");

        }

        

        //解锁

        [_myLockunlock];

    }

     

    @end



    二:NSOpreation:

     

     

    1.用NSOpreation实现在线下载图片

     

    #import "ViewController.h"

    #import "ImageOperation.h"

     

    @interfaceViewController ()

    {

        NSOperationQueue *_queue;

    }

     

    @end

     

    @implementation ViewController

     

    - (void)viewDidLoad {

        [superviewDidLoad];

        // Do any additional setup after loading the view, typically from a nib.

        

        

        //创建图片视图

        UIImageView *myImageView = [[UIImageViewallocinitWithFrame:CGRectMake(40,100300,300)];

        [self.viewaddSubview:myImageView];

        

        //使用NSOperatio自定制类型实现多线程

        

        //1.创建一个队列

        _queue = [[NSOperationQueueallocinit];

        

        //队列里面同时执行的线程最大数量

        //例如往队列里面加了20个线程,只会执行10个,其他的线程要等这10个中的某个执行完成之后,才能执行

        _queue.maxConcurrentOperationCount =10;

        

        //2.创建ImageOperation对象

        ImageOperation *op = [[ImageOperationallocinit];

        //设置下载链接

        op.urlString=@"http://g.hiphotos.baidu.com/image/pic/item/4034970a304e251fb3145e6ca586c9177e3e5346.jpg";

        //设置显示的视图

        op.imgView = myImageView;

        

        //添加到队列

        [_queueaddOperation:op];

        

        //ASIHttpRequest: NSOperation

        

    }

     

    ////////////////////////////////////////////////////////////////////////////////////////////////////////

     

     

    #import "ImageOperation.h"

     

    @implementation ImageOperation

     

    //使用NSOperation自定制对象创建线程时的执行体

    -(void)main

    {

        //下载图片

        NSURL *url = [NSURLURLWithString:self.urlString];

        

        NSData *data = [NSDatadataWithContentsOfURL:url];

        

        //回到主线程修改UI

        [selfperformSelectorOnMainThread:@selector(refreshUI:)withObject:data waitUntilDone:YES];

        

    }

     

    - (void)refreshUI:(NSData *)data

    {

        self.imgView.image = [UIImageimageWithData:data];

    }

     

     

    @end



     

     

    2.使用NSOperation创建多线程:

     

     

    - (void)viewDidLoad {

        [superviewDidLoad];

        // Do any additional setup after loading the view, typically from a nib.

        

        //NSOperation实现多线程

        //1.创建队列

        _queue = [[NSOperationQueueallocinit];

        

        //2.创建NSInvocationOperation对象

        /*

         第一个参数:线程执行体方法所属的对象

         第二个参数:线程执行体方法

         第三个参数:线程执行体方法传递的实参

         */

        NSInvocationOperation *op1 = [[NSInvocationOperationalloc]initWithTarget:selfselector:@selector(threadOne)object:nil];

        //线程结束之后执行的代码块

        [op1 setCompletionBlock:^{

            NSLog(@"线程一结束");

        }];

        

        //3.开启线程

        [_queueaddOperation:op1];

        

        

        //第二种实现线程的方式

        NSBlockOperation *op2 = [NSBlockOperationblockOperationWithBlock:^{

            //线程的执行体

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

                NSLog(@"执行线程二:%d",i);

            }

        }];

        //线程执行结束后调用的代码块

        [op2 setCompletionBlock:^{

            NSLog(@"线程二结束");

        }];

        

        //添加到队列里面

        [_queueaddOperation:op2];

        

    }

    //线程执行体方法

    - (void)threadOne

    {

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

            NSLog(@"执行了线程一:%d", i);

        }

    }

     

     

    三:GCD:

     

    1.用GCD实现多线程:

     

     

     

    #import "ViewController.h"

     

    @interfaceViewController ()

     

    @end

     

    @implementation ViewController

     

    - (void)viewDidLoad {

        [superviewDidLoad];

        // Do any additional setup after loading the view, typically from a nib.

        

        

        //1.同一块代码执行多次

        //[self testApply];

        

        //2.代码只执行一次

    //    [self testOnce];

    //    [self testOnce];

    //    [self testOnce];

    //    [self testOnce];

        

        //3.在一段时间之后执行代码块

        //[self testAfter];

        

        //4.线程组(group)

        //[self testGroup];

        

        //5.在某几个线程都执行完成之后,并在另外几个线程都执行完成之前,需要执行一些代码

        [selftestBarrier];

        

    }

     

     

    //5.在某几个线程都执行完成之后,并在另外几个线程都执行完成之前,需要执行一些代码

    - (void)testBarrier

    {

        //队列不能是系统的全局队列

        dispatch_queue_t concurrentQueue =dispatch_queue_create("concurrentQueue",DISPATCH_QUEUE_CONCURRENT);

        

        //线程一

        dispatch_async(concurrentQueue, ^{

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

                NSLog(@"线程一:%d", i);

            }

        });

        

        //线程二

        dispatch_async(concurrentQueue, ^{

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

                NSLog(@"线程二:%d", i);

            }

        });

        

        //在线程一和线程二都执行完成之后,并且在线程三执行之前,调用一段代码块

        dispatch_barrier_async(concurrentQueue, ^{

            NSLog(@"barrier");

        });

        

        //线程三

        dispatch_async(concurrentQueue, ^{

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

                NSLog(@"线程三:%d", i);

            }

        });

        

        

    }

     

     

    //4.多个线程都执行之后去执行一些代码

    - (void)testGroup

    {

        //线程组

        dispatch_group_t group =dispatch_group_create();

        

        

        /*

         第一个参数:线程组

         第二个参数:线程所在的队列

         第三个参数:线程的执行体

         */

        dispatch_group_async(group,dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0), ^{

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

                NSLog(@"执行了线程一:%d", i);

            }

        });

        dispatch_group_async(group,dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0), ^{

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

                NSLog(@"执行了线程二:%d", i);

            }

        });

        

        //在该组的所有线程都执行结束时做执行某段代码

        dispatch_group_notify(group,dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0), ^{

            NSLog(@"所有线程都执行完成");

        });

        

    }

     

    //3.在一段时间之后执行代码块

    - (void)testAfter

    {

        NSLog(@"执行之前");

        

        //DISPATCH_TIME_NOW:表示当前的时间

        //当前时间的十秒之后

        dispatch_time_t myTime =dispatch_time(DISPATCH_TIME_NOW,NSEC_PER_SEC*10);

        //队列

        //创建一个并行的队列

        dispatch_queue_t concurrentQueue =dispatch_queue_create("concurrentQueue",DISPATCH_QUEUE_CONCURRENT);

        /*

         第一个参数:代码块执行的时间

         第二个参数:代码块的线程所在的队列

         第三个参数:执行的代码块

         */

        dispatch_after(myTime, concurrentQueue, ^{

            NSLog(@"执行了代码块");

        });

    }

     

    //2.代码只执行一次

    //通常用来实现单例

    - (void)testOnce

    {

        staticdispatch_once_t onceToken;

        

        dispatch_once(&onceToken, ^{

            NSLog(@"执行了一次");

        });

    }

     

    //1.同一块代码执行多次

    - (void)testApply

    {

        /*

         第一个参数:代码块执行多少次

         第二个参数:线程所在的队列

         第三个参数:线程的执行体

         */

        dispatch_queue_t globalQueue =dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0);

        

        //参数表示当前是第几次执行

        dispatch_apply(10, globalQueue, ^(size_t time) {

            //线程的执行体

            NSLog(@"执行到了第%ld", time);

        });

    }

     

    - (void)didReceiveMemoryWarning {

        [superdidReceiveMemoryWarning];

        // Dispose of any resources that can be recreated.

    }

     

    @end

     

     

    2.GCD实现多线程2:

     

     

    - (void)viewDidLoad {

        [superviewDidLoad];

        // Do any additional setup after loading the view, typically from a nib.

        

        

        //GCD实现多线程

        

        //一、GCD的队列

        //1.主线程所在的串行队列

        //系统自动创建了这个队列,我们只要获取后使用

        dispatch_queue_t mainQueue =dispatch_get_main_queue();

        

        //2.系统的全局并行队列

        //系统自动创建了这个队列,我们只能获取后使用

        

        /*

         第一个参数:队列的优先级

         第二个参数:APPLE公司保留的参数

         */

        dispatch_queue_t globalQueue =dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0);

        

        

        //3.自己创建的队列

        //1)串行队列

        /*

         第一个参数:队列的标识符

         第二个参数:用来区分是串行队列还是并行队列

         DISPATCH_QUEUE_SERIAL:串行队列

         DISPATCH_QUEUE_CONCURRENT:并行队列

         */

        dispatch_queue_t serialQueue =dispatch_queue_create("serialQueue",DISPATCH_QUEUE_SERIAL);

        

        //2)并行队列

        dispatch_queue_t concurrentQueue =dispatch_queue_create("concurrentQueue",DISPATCH_QUEUE_CONCURRENT);

        

        //二、GCD创建线程

        //1、异步将线程的执行体代码放到队列执行

        /*

         第一个参数:队列

         第二个参数:线程的执行体代码

         */

        dispatch_queue_t queueOne =dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0);

        dispatch_async(queueOne, ^{

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

                NSLog(@"执行了线程一:%d", i);

            }

        });

        

        

        //2、同步将线程的执行体放到队列执行

        dispatch_sync(queueOne, ^{

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

                NSLog(@"执行了线程二:%d", i);

            }

        });

        

    }

     

    - (void)didReceiveMemoryWarning {

        [superdidReceiveMemoryWarning];

        // Dispose of any resources that can be recreated.

    }

     

    @end

     

    3.GCD的串行和并行队列:

     

     

     

    #import "ViewController.h"

     

    @interfaceViewController ()

     

    @end

     

    @implementation ViewController

     

    - (void)viewDidLoad {

        [superviewDidLoad];

        // Do any additional setup after loading the view, typically from a nib.

        

        //1.以同步的方式在串行队列创建两个线程

        //[self testSyncWithSerialQueue];

        

        //2.以同步的方式在并行队列创建两个线程

        //[self testSyncWithConcurrentQueue];

        

        //3.以异步的方式在串行队列创建两个线程

        //[self testAsyncWithSerialQueue];

        

        //4.以异步的方式在并行队列创建两个线程

        [selftestAsyncWithConcurrentQueue];

        

    }

     

    //4.以异步的方式在并行队列创建两个线程

    //前面的线程和后面的线程同时执行

    - (void)testAsyncWithConcurrentQueue

    {

        //创建并行队列

        dispatch_queue_t concurrentQueue =dispatch_queue_create("concurrentQueue",DISPATCH_QUEUE_CONCURRENT);

        

        //线程一

        dispatch_async(concurrentQueue, ^{

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

                NSLog(@"线程一:%d", i);

            }

        });

        //线程二

        dispatch_async(concurrentQueue, ^{

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

                NSLog(@"线程二:%d", i);

            }

        });

        

    }

     

     

    //3.以异步的方式在串行队列创建两个线程

    //前面的线程执行完成,后面的线程才开始执行

    - (void)testAsyncWithSerialQueue

    {

        //串行队列

        dispatch_queue_t serialQueue =dispatch_queue_create("myQueue",DISPATCH_QUEUE_SERIAL);

        //线程一

        dispatch_async(serialQueue, ^{

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

                NSLog(@"线程一:%d", i);

            }

        });

        //线程二

        dispatch_async(serialQueue, ^{

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

                NSLog(@"线程二:%d", i);

            }

        });

    }

     

    //2.以同步的方式在并行队列创建两个线程

    //前面的线程执行结束,才开始执行后面的线程

    - (void)testSyncWithConcurrentQueue

    {

        //获取全局并行队列

        dispatch_queue_t globalQueue =dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0);

        

        //线程一

        dispatch_sync(globalQueue, ^{

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

                NSLog(@"线程一:%d", i);

            }

        });

        //线程二

        dispatch_sync(globalQueue, ^{

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

                NSLog(@"线程二:%d", i);

            }

        });

        

    }

     

     

    //1.以同步的方式在串行队列创建两个线程

    //前面的线程执行完成之后,才开始执行后面的线程

    - (void)testSyncWithSerialQueue

    {

        //创建一个串行队列

        dispatch_queue_t serialQueue =dispatch_queue_create("serialQueue",DISPATCH_QUEUE_SERIAL);

        

        //线程一

        dispatch_sync(serialQueue, ^{

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

                NSLog(@"线程一:%d", i);

            }

        });

        //线程二

        dispatch_sync(serialQueue, ^{

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

                NSLog(@"线程二:%d", i);

            }

        });

        

        

    }

     

     

     

     

  • 相关阅读:
    编解码学习笔记(十):Ogg系列
    php大小写问题
    thinkphp5内置标签
    php递归实现无限级分类
    thinkphp5项目--企业单车网站(五)
    控制器不存在:appadmincontrollerDocument
    Cookie与Session的区别与联系及生命周期
    thinkphp5项目--企业单车网站(四)
    thinkphp5项目--企业单车网站(三)
    thinkphp使后台的字体图标显示异常
  • 原文地址:https://www.cnblogs.com/leixu/p/5159775.html
Copyright © 2011-2022 走看看