多线程

作者: liyoucheng2014 | 来源:发表于2018-12-22 19:50 被阅读0次

    何为多线程

    线程就是“一个CPU执行的一条无分叉的命令列”

    并发与并行

    并发(concurrent)
    指的是一种现象,一种经常出现,无可避免的现象。它描述的是“多个任务同时发生,需要被处理”这一现象。侧重点在于“发生”

    并行(parallelism)
    指的是一种技术,一个同时处理多个任务的技术。他描述了一种能够同时处理多个任务的能力。侧重点在于“运行”

    小结: 并发是一种现象,面对这一现象,我们首先创建多个多线程,真正加快程序运行速度的,是并行技术。也就是让多个CPU同时工作。而多线程,是为了让多个CPU同时工作成为可能。

    同步与异步

    描述的是任务之间的先后顺序问题。

    小结:在需要同时处理IO和UI的情况下,真正起作用的是异步,而不是多线程。

    GCD

    队列
    串行队列(FIFO,每次只执行一个)
    并发队列(FIFO,多个任务并发)
    主队列(特殊的串行队列,一定在主线程中执行)

    执行方式
    同步执行
    异步执行

    队列名字 同步 异步
    主队列 在主线程中执行 在主线程中执行
    串行队列 在当前线程中执行 新建线程执行
    并发队列 在当前线程中执行 新建线程执行

    GCD的死锁问题

    向当前串行队列中同步派发一个任务
    Swift

            let mainQueue = DispatchQueue.main
            let block = { () in
                
                print("当前线程: \(Thread.current)")
            }
            mainQueue.sync(execute: block)
    

    OC

    dispatch_sync(dispatch_get_main_queue(), ^{
            
            NSLog(@"当前线程 %@", [NSThread currentThread]);
        });
    

    主队列在执行dispatch_sync,随后队列中新增一个任务block。因为主队列是同步队列,所以block要等dispatch_sync执行完才能执行,但是dispatch_sync是同步派发,要等block执行完才算是结束。在主队列中的两个任务互相等待,导致了死锁。

    GCD任务组

    Swift

    let group = DispatchGroup()
    let serialQueue = DispatchQueue(label: "com")
    
    serialQueue.async(group: group, execute: { () -> Void in
          for _ in 0..<2 {
              print("group-serial \(Thread.current)")
          }
    })
            
    serialQueue.async(group: group, execute: { () -> Void in
          for _ in 0..<3 {
               print("group-02 - %@ \(Thread.current)")
           }
    })
            
    let workItem = DispatchWorkItem {
          print("完成 - \(Thread.current)")
    }
            
    group.notify(queue: DispatchQueue.main, work: workItem)
    

    OC

    dispatch_group_t group = dispatch_group_create();
        dispatch_queue_t serial = dispatch_queue_create("cn.gigahome.w", NULL);
    //    dispatch_queue_t concurrentQueue = dispatch_queue_create("cn.gigahome.w", DISPATCH_QUEUE_CONCURRENT);
        dispatch_group_async(group, serial, ^{
            
            for (int i = 0; i < 2; i++) {
                
                NSLog(@"group serial %@", [NSThread currentThread]);
            }
        });
        
        dispatch_group_async(group, serial, ^{
            
            for (int i = 0; i < 3; i++) {
                
                NSLog(@"group 02 %@", [NSThread currentThread]);
            }
        });
        
        dispatch_group_notify(group, dispatch_get_main_queue(), ^{
           
            NSLog(@"完成 %@", [NSThread currentThread]);
        });
    

    wait
    leave

    dispatch_after

    Swift

    let mainQueue = DispatchQueue.main
    let time = DispatchTime.now() + 5.0
    print("\(Thread.current)")
    mainQueue.asyncAfter(deadline: time) {
         print("\(Thread.current)")
    }
    

    OC

    dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC));
        NSLog(@"当前线程 %@", [NSThread currentThread]);
        dispatch_after(time, dispatch_get_main_queue(), ^{
            
            NSLog(@"当前线程 %@", [NSThread currentThread]);
        });
    

    NSOperation

    Swift

    let operation = BlockOperation { () -> Void in
        print("doSomething1 \(Thread.current)")
    }
    
    operation.addExecutionBlock { () -> Void in
        print("doSomething2 \(Thread.current)")
    }
    
    operation.start()
    

    OC

     NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
           
            NSLog(@"%@", [NSThread currentThread]);
        }];
        
        [operation addExecutionBlock:^{
           
            NSLog(@"execution block %@", [NSThread currentThread]);
        }];
        
        [operation start];
    

    NSOperationQueue

    队列名字 NSOperationQueue GCD
    主队列 OperationQueue.main DispatchQueue.main
    串行队列 自建队列maxConcurrentOperationCount为1 DispatchQueue(label: "")
    并发队列 自建队列maxConcurrentOperationCount大于1 DispatchQueue(label: "",attributes:.concurrent)

    NSOperationQueue会为每一个NSOperation建立线程并调用他们的start方法
    Swift

    let queue = OperationQueue()
    queue.maxConcurrentOperationCount = 3
    
    let operation = BlockOperation { () -> Void in
        print("exec block1 -- \(Thread.current)")
    }
    
    operation.addExecutionBlock { () -> Void in
        print("exec block2 -- \(Thread.current)")
    }
    
    operation.addExecutionBlock { () -> Void in
        print("exec block3 -- \(Thread.current)")
    }
    queue.addOperation(operation)
    print("操作结束")
    

    OC

    NSOperationQueue *queue = [[NSOperationQueue alloc] init];
        queue.maxConcurrentOperationCount = 3;
        
        NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
           
            NSLog(@"exec block1 -- %@", [NSThread currentThread]);
        }];
        
        [operation addExecutionBlock:^{
           
            NSLog(@"exec block2 -- %@", [NSThread currentThread]);
        }];
        
        [operation addExecutionBlock:^{
            
            NSLog(@"exec block3 -- %@", [NSThread currentThread]);
        }];
        [queue addOperation:operation];
        NSLog(@"操作结束");
    

    NSOperation新特性

    取消任务

    operation.cancel()
    queue.cancelAllOperations()
    

    设置依赖

    operation2.addDependency(operation)
    

    NSOperationQueue的暂停与恢复

    queue.suspended = true(挂起)
    queue.suspended = false(恢复)
    

    NSOperation的优先级

    typedef NS_ENUM(NSInteger, NSOperationQueuePriority) {
        NSOperationQueuePriorityVeryLow = -8L,
        NSOperationQueuePriorityLow = -4L,
        NSOperationQueuePriorityNormal = 0,
        NSOperationQueuePriorityHigh = 4,
        NSOperationQueuePriorityVeryHigh = 8
    };
    
    public enum QueuePriority : Int {
    
            case veryLow
    
            case low
    
            case normal
    
            case high
    
            case veryHigh
        }
    

    NSOperationQueue也不能完全保证优先级高的任务一定先执行。

    NSOperation和GCD如何选择

    GCD以block为单位,代码简洁。同时GCD中的队列、组、信号量、source、barriers都是组成并行编程的基本原语。
    对于一次性的计算,或是仅仅为了加快现有方法的运行速度,选择轻量化的GCD更加方便

    NSOperation可以用来规划一组任务之间的依赖关系,设置他们的优先级,任务能别取消。队列可以暂停、恢复。NSOperation还可以子类化。

    其它

    dispatch_suspenddispatch_resume

    dispatch_suspend(queue) //暂停某个队列  
    dispatch_resume(queue)  //恢复某个队列  
    

    dispathc_once

    + (Manager *)sharedInstance {
        static Manager *sharedManagerInstance = nil;
        static dispatch_once_t once;
        
        dispatch_once(&once, ^{
            sharedManagerInstance = [[Manager alloc] init];
        });
        
        return sharedManagerInstance;
    }
    

    dispatch_barrier_async

    dispatch_async(queue, block1_for_reading)  
    dispatch_async(queue, block2_for_reading)
    
    dispatch_barrier_async(queue, block_for_writing)
    
    dispatch_async(queue, block3_for_reading)  
    dispatch_async(queue, block4_for_reading)  
    

    dispatch_semaphore

    let queue = DispatchQueue.init(label: "cn.gigahome.w", attributes: DispatchQueue.Attributes.concurrent)
    queue.async {
         print("读数据1")
    }
    queue.async {
         print("读数据2")
    }
    let workItem = DispatchWorkItem.init(qos: DispatchQoS.default, flags: DispatchWorkItemFlags.barrier) {
         print("开始写数据------写数据完成")
    }
    queue.async(execute: workItem)
    queue.async {
         print("读数据3")
    }
    queue.async {
         print("读数据4")
    }
    

    iOS多线程编程总结
    Swift GCD
    iOS开发多线程篇—线程安全

    相关文章

      网友评论

          本文标题:多线程

          本文链接:https://www.haomeiwen.com/subject/byzbkqtx.html