zoukankan      html  css  js  c++  java
  • Thread 多线程

    Thread 多线程

    1.多线程的概念

    程序: 代码编译后, 形成执行文件

    进程: 程序运行起来, 就是进程, 进程提供程序运行所需的端口等

    线程: 分配资源

    进程中至少要有一个线程(主线程), 如果主线程阻塞, 程序就会假死; 如果主线程停止运行, 程序将终止

    2.没有使用多线程的应用, 有什么问题?

    当处理复杂的数据操作时, 就会阻塞主线程

    3.多线程的方式

    a.NSObject

    b.NSThread

    c.NSOperationQueue

    d.GCD

    4.需不需要把所有的操作都放在子线程上?(主线程和子线程的区别)

    a.能够调度资源大小不一样(主:10M, 子:5M)

    b.子线程不能释放通过便利构造器创建的对象, 原因: 子线程没有自动释放池, autorelease的对象无法得到释放

    c.刷新UI的操作必须在主线程中执行, 原因: 在子线程中刷新UI会失败

    5.多线程的优缺点

    优点: 可以为主线程分担操作, 避免出现主线程阻塞; 执行效率高

    缺点: 资源消耗高; 资源抢夺; 需要管理

    6.多个线程使用同一块资源时, 会出现资源抢夺, 解决方案: 当操作这块资源时, 加锁, 离开时, 解锁; 保证同一个时刻只能有一个线程操作资源

    在story中添加button, 关联方法

        

    - (void)viewDidLoad {
        [super viewDidLoad];
        // Do any additional setup after loading the view, typically from a nib.
        [NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(rotation) userInfo:nil repeats:YES];
    }
    
    - (void)didReceiveMemoryWarning {
        [super didReceiveMemoryWarning];
        // Dispose of any resources that can be recreated.
    }
    - (void)rotation {
        [UIView beginAnimations:@"旋转" context:nil];
        [UIView setAnimationCurve:UIViewAnimationCurveLinear];
        [UIView setAnimationDuration:0.15];
        self.imageView.transform = CGAffineTransformRotate(self.imageView.transform, M_PI_4);
        [UIView commitAnimations];
    }
    
    - (IBAction)server:(id)sender {
        @autoreleasepool {
            for (NSInteger i = 1; i <= 1000; i++) {
                @autoreleasepool {
                    NSString *string = [NSString stringWithFormat:@"接了%ld个客人", i];
                    NSLog(@"%@", string);
                }
                //线程休眠
                [NSThread sleepForTimeInterval:1];
            }
            NSThread *currentThread = [NSThread currentThread];
            NSLog(@"%@", currentThread);
        }
      }

        NSObject中提供一些和线程相关的方法

        在主线程执行某些方法

        [self performSelectorOnMainThread: withObject: waitUntilDone:]

        在后台执行某些方法(在后台的子线程执行)

    - (IBAction)serverWithNSObject:(id)sender {
    //    在后台执行某些方法(在后台的子线程执行)
        [self performSelectorInBackground:@selector(server:) withObject:nil];
    }

    NSThread, 线程类, 继承于NSObject

    - (IBAction)serverWithNSThread:(id)sender {
        //获取主线程
        NSThread *mainThread = [NSThread mainThread];
        NSLog(@"%@", mainThread);
        //线程所占的栈区大小, 4KB
        NSLog(@"%lu", mainThread.stackSize);
        //创建子线程
        NSThread *subThread = [[NSThread alloc] initWithTarget:self selector:@selector(server:) object:self];
        subThread.name = @"子线程";
    //    [subThread start];
        NSLog(@"%@", subThread);
        NSLog(@"%lu", subThread.stackSize);
        //创建线程
        [NSThread detachNewThreadSelector:@selector(server:) toTarget:self withObject:nil];
        //线程休眠
    //    [NSThread sleepForTimeInterval:<#(NSTimeInterval)#>]
        //获取当前线程
    //    NSThread *currentThread = [NSThread currentThread];
    //    NSLog(@"%@", currentThread);
    }

        NSOperationQueue, 操作队列类, 继承于NSObject, 操作队列内存放各种操作, 这些操作最终在操作队列对应的线程上执行

        队列, 存放数据的方式: 先进先出(FIFO)

        NSOperation, 操作类, 可以存放在操作队列中, 抽象类, 操作只能执行一次, 它的子类有:

        NSInvocationOperation

        NSBlockOperation

    - (void)eat {
        for (NSInteger i = 1; i < 100; i++) {
            NSLog(@"吃了%ld只龙虾", i);
        }
    }
    
    - (IBAction)serverWithNSOperationQueue:(id)sender {
        NSInvocationOperation *invocation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(eat) object:nil];
        //执行操作(在主线程中执行)
    //    [invocation start];
        
        NSBlockOperation *block = [NSBlockOperation blockOperationWithBlock:^{
            for (NSInteger i = 1; i <= 100; i++) {
                NSLog(@"喝了%ld罐青岛啤酒", i);
            }
        }];
    //    [block start];
        //操作建立依赖关系
        [invocation addDependency:block];
        //创建一个队列
        NSOperationQueue *queue = [[NSOperationQueue alloc] init];
        //最大并发数
        //并发数为1的队列, 叫串行队列
        //并发数大于1的队列, 叫并发队列
        queue.maxConcurrentOperationCount = 1;
        //向队列中添加操作(只有把操作添加到队列, 操作就会在队列对应的线程中执行)
    //    [queue addOperation:invocation];
    //    [queue addOperation:block];
        //同时添加多个操作
        [queue addOperations:@[invocation, block] waitUntilFinished:NO];
        //主队列, 绑定主线程
    //    NSOperationQueue *mainQueue = [NSOperationQueue mainQueue];
    }

        GCD, Grand central Dispatch, 大中央调度, 多线程优化技术, 通过C语言实现, 执行效率高

    - (IBAction)serverWithGCD:(id)sender {
        三种队列
       1.主调队列, 绑定主线程, 并发数为1
       dispatch_queue_t: 队列数据类型
       mianQueue: 变量名
       dispatch_get_main_queue: 调用函数
        dispatch_queue_t mianQueue = dispatch_get_main_queue();
        NSLog(@"%@", mianQueue);
        
        2.全局队列, 绑定子线程, 并发队列
        参数1: 优先级
        参数2: 预留参数, 为未来做准备, 一般写0
        dispatch_queue_t globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
        NSLog(@"%@", globalQueue);
        
        3.自定义队列, 绑定子线程
        参数1: 队列的标识符, 通过调试工具可以查看
        参数2: 串行或并发
        dispatch_queue_t customQueu = dispatch_queue_create("com.huige", DISPATCH_QUEUE_SERIAL);
        NSLog(@"%@", customQueu);
        
        在队列中, 执行某些操作, 有两种方式:
        1.同步执行
        参数1: 操作执行队列
        参数2: block, 写你想要执行的操作
        dispatch_sync(globalQueue, ^{
            for (NSInteger i = 1; i <= 100; i++) {
                NSLog(@"%ld", i);
            }
        });
        
        2.异步执行
        dispatch_async(mianQueue, ^{
            for (NSInteger i = 1; i <= 100; i++) {
                NSLog(@"笑场%ld次", i);
            }
        });
        延迟多少秒执行某些操作
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            NSLog(@"再见");
        });
        
    //    dispatch_after(<#dispatch_time_t when#>, <#dispatch_queue_t queue#>, <#^(void)block#>)
        
    }

    创建单例

    Singleton.h
    #import <Foundation/Foundation.h>
    
    @interface Singleton : NSObject
    
    + (Singleton *)sharedSingleton;
    
    @end
    Singleton.m
    #import "Singleton.h"
    
    @implementation Singleton
    1.主线程创建
    + (Singleton *)sharedSingleton {
        static Singleton *singleton = nil;
        if (singleton == nil) {
            singleton = [[Singleton alloc] init];
        }
        return singleton;
    }
    
    2.互斥锁
    + (Singleton *)sharedSingleton { static Singleton *singleton = nil; //互斥锁 @synchronized(self) { if (singleton == nil) { singleton = [[Singleton alloc] init]; } } return singleton; }
    3.dispatch_once 保证代码只执行一次
    + (Singleton *)sharedSingleton {
    static Singleton *singleton = nil; 
    //保证代码只执行一次, dispatch_once
    static dispatch_once_t onceToken;
    dispatch_once(
    &onceToken, ^{ singleton = [[Singleton alloc] init];
    });
    return singleton;
    }
    @end

    多线程购票

    效果图:

    具体代码: 在storyboard中添加一个label和开始售票的button, 关联方法和属性

    #import "TicketViewController.h"
    
    @interface TicketViewController ()
    - (IBAction)start:(id)sender;
    @property (strong, nonatomic) IBOutlet UILabel *label;
    
    @property (nonatomic, assign) NSInteger totalCount;//总票数
    @property (nonatomic, assign) NSInteger saleCount;//卖出的票数
    @property (nonatomic, strong) NSLock *lock;//
    
    @end
    
    @implementation TicketViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        // Do any additional setup after loading the view.
        self.totalCount = 100;
        self.saleCount = 0;
        self.lock = [[NSLock alloc] init];
    }
    
    - (void)didReceiveMemoryWarning {
        [super didReceiveMemoryWarning];
        // Dispose of any resources that can be recreated.
    }
    
    - (void)refreshUI {
        [UIView transitionWithView:self.label duration:0.2 options:UIViewAnimationOptionTransitionCurlUp animations:^{
            self.label.text = [NSString stringWithFormat:@"%ld", self.totalCount];
        } completion:^(BOOL finished) {
            [self.lock unlock];
        }];
       }
    
    - (void)sale {
        while (YES) {
            [NSThread sleepForTimeInterval:0.5];
            [self.lock lock];
            if (self.totalCount > 0) {
                self.totalCount--;
                //在主线程中执行
                [self performSelectorOnMainThread:@selector(refreshUI) withObject:nil waitUntilDone:NO];
                self.saleCount++;
                NSLog(@"%@, 卖了%ld张票, 剩余%ld张票", [NSThread currentThread], self.saleCount, self.totalCount);
            } else {
                NSLog(@"票卖完了, 明年再回家吧!");
                return;
            }
        }
    }
    
    
    - (IBAction)start:(id)sender {
        //售票窗口(子线程)
        NSThread *thread1 = [[NSThread alloc] initWithTarget:self selector:@selector(sale) object:nil];
        thread1.name = @"窗口1";
        [thread1 start];
        
        // 第二个售票窗口
        NSThread *thread2 = [[NSThread alloc] initWithTarget:self selector:@selector(sale) object:nil];
        thread2.name = @"窗口2";
        [thread2 start];
    }
    @end
  • 相关阅读:
    python 基础——generate生成器
    python 基础——*args和**kwargs
    猴子补丁
    python 元类——metaclass
    javascript 数据类型
    C/C++语言实现单链表(带头结点)
    C++仿函数和回调函数的异同
    C++利用动态数组实现顺序表(不限数据类型)
    const的用法
    数据结构之线性表
  • 原文地址:https://www.cnblogs.com/OrangesChen/p/5046733.html
Copyright © 2011-2022 走看看