• iOS多线程系统整理 swift


    多线程   是一个应用程序内多个代码的执行路径,执行线程,同时在同一时间里执行不同的任务。

    三种:

    1、NSTread

    2、Cocoa NSOperation (NSOperation,NSOperationQueue)

    3、GrandCentralDispatch:GCD


    1NSTread

    相对最简单,需要自己管理线程的生命周期和线程同步(加锁会有一定的系统开销)

    两种应用方式:

    需要传递三个参数:

    selector:线程执行方法""

    target:方法所在的对象

    argument:传递给方法的参数,可选nil

    一、直接创建线程,自动运行线程

    // Class Method

    class func detachNewThreadSelector(selector:Selector,toTarget target:AnyObject,withObject argument:AnyObject?)

    二、先创建一个线程对象,手动运行线程,在运行之前可设置线程优先级等信息。

    convenience init(target:AnyObject,selector:Selector,object argument:AnyObject?)

    for example

    // download image method

    func downloadImage()

    {

    var imageUrl = "https://www.baidu.com/img/bdlogo.png"

    var data = NSData.dataWithContentsOfURL(NSURL.URLWithString(imageUrl),options:nil,error:nil)

    println(data.length)

    }

    override func viewDidLoad(){

    super.viewDidLoad()

    // 第一种方式

    NSThread.detachNewThreadSelector("downloadImage",toTarget:self,withObject:nil)

    // 第二种方式

    var downloadImageThread = NSThread(target:self,selector:"downloadImage",object:nil)

    dowloadImageThread.start()

    }

    线程同步,通过锁来实现,每个线程有一个锁,锁 与 特定的线程关联。

    for example

    // 定义两个线程

    var thread1,thread2:NSThread?

    // 线程条件

    let condition1 = NSCodition()

    let condition2 = NSCodition()

    // two method for thread 

    func method1(sender: AnyObject)

    {

      for var i = 0; i <10; i++

      {

      println("thread 1 running (i)")

      sleep(1)

      if i == 2

      {

      thread2!.start()

    // lock

    condition1.lock()

    condition1.wait()

    condition1.unlock()

      }

      }

    println(thread 1 over)

    //

    condition2.signal()

    }

    // 

    func method2(sender:AnyObject)

    {

      for var i=0;i<10;i++

      {

      println("thread 2 running (i)")

      sleep(1)

      if i ==2

      {

    //  active thread 1

      condition1.signal()

    // lock 

    condition2.lock()

    condition2.wait()// stop waitting

    condition2.unlock()

      }

      }

    println("thread 2 over")

    }

    // RUN

    thread2 = NSThread (target:self , selector:"method2:",object:nil)

    thread1 = NSThread(target:self,selector:"method1",object:nil)

    控制台输出

    thread 1 running 0

    thread 1 running 1

    thread 1 running 2

    thread 2 running 0

    thread 2 running 1

    thread 2 running 2

    thread 1 running 3

    thread 1 running 4

    thread 1 running 5

    thread 1 running 6

    thread 1 running 7

    thread 1 running 8

    thread 1 running 9

    thread 1 over

    thread 2 running 3

    thread 2 running 4

    thread 2 running 5

    thread 2 running 6

    thread 2 running 7

    thread 2 running 8

    thread 2 running 9

    线程1 2是同步关系,启动2,挂起 1,激活1,挂起2,有效避免了线程1占用一个资源时,引起线程2不能访问的问题。


    NSOperation 两种方式

     两个子类 NSInvocationOperation   NSBlockOperation

    // creat instance

    var operation = NSInvocationOperation(target:self,selector:"dowloadImage",object:nil)

    var queue = NSOperationQueue()

    queue.addOperation(operation)

    后台建立一个线程

    Queue队列中可以加入很多个operation 可以把它看做是一个线程池子,可以设置线程池中的线程数,即并发操作数。

    默认是:-1,-1表示没有限制,同时运行队列中的全部操作。

    queue.maxConcurrentOperationCount = 6

    // ervery operation come to an end   

    var completionBlock:(()->Void)?

    operation.completionBlock = completionBlock

    dispatch_after(dispatch_time(DISPATCH_TIME_NOW,4),dispatch_get_main_queue(),{println("complete")})

    // cancell

    queue.cancelAllOperations()

     继承NSOperation   把子类的对象放到NSOperationQueue队列中 ,一旦加入,就处理这个,直到操作完成,队列被释放。

    // creat DrinkOperation.swift 继承 NSOperation   且  实现main方法   

    import UIKit

    class DrinkOperation:NSOperation{

      override func main()

      {

      println("drink")

      }

    // e.g.

    // creat a  instance

    var queue1 = NSOperationQueue()

    // creat a operation

    var drinkOperation = DrinkOperation()

    // add 

    queue1.addOperation(drinkOperation)


    Grand Central Dispatch

    多核编程

    底层也是用线程实现,queue可以接受任务,先到先执行顺序来执行,也可以并发或串行执行。

    同步或异步

    优点多多:基于C,融入面向对象,Block,易用,性能上自动根据系统负载来增减线程数量,无需加锁。

    种方法:

    自己创建队列

    func dispatch_queue_create(label:UnsafePointer<Int8>,attr:dispation_queue_attr_t!)->dispatch_queue_t!

    label:参数代表队列名称,可以任意名

    DISPATCH_QUEUE_CONCURRENT  并行

    DISPATCH_QUEUE_SERIAL 串行  

    //e.g.

    var serialQueue = dispatch_queue_create("serialQueue_1",DISPATCH_QUEUE_SERIAL)

    var concurrentQueue = dispatch_queue_create("concurrentQueue_1",DISPATCH_QUEUE_CONCURRENT)

     获取系统的全局队列

    func dispatch_get_global_queue(identifier:Int,flags:UInt)->dispatch_gueue_t!

    参数 identifier   执行优先级  ,4个优先级

    DISPATCH_QUEUE_PRIORITY_HIGH

    DISPATCH_QUEUE_PRIORITY_DEFAULT

    DISPATCH_QUEUE_PRIORITY_LOW

    DISPATCH_QUEUE_PRIORITY_BACKGROUND    非常低的有相机,用于不太关心的后台任务

    // e.g.

    var globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0)

    在主线程的Main dispatch queue

    在主线程里执行的队列(只有一个主线程)

    一切跟UI相关的操作都放到主线程中执行

    func dispatch_get_main_queue()->dispatch_queue_t!

    // e.g.

    var mainQueue = dispatch_get_main_queue()


    追加任务到队里的  两个方法:
    一 dispatch_async  异步追加Block

    async = asynchronous 异步

    func dispatch_async(queue:dispatch_queue_t!,block:dispatch_block_t!)

    第一个参数:GCD队列
    第二个参数:block

    // e.g.

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0),{()->Void in

    //  耗时代码块

    //执行完  调用主线程刷新界面

    dispatch_async(dispatch_get_main_queue(),{()->Void in

    //通知主线程刷新

    })

    })

    二 dispatch_sync 同步追加Block

    与之前相反,block结束之前,dispatch_sync会一直等待,等待队列前面的所有任务完成后才执行追加的任务。

    func dispatch_sync()

    // e.g.

    dispatch_sync(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0),{()->Void in

    println("sync1")

    })

    加到 global_queue异步队列中,不会造成锁死,但会一直等待代码执行完毕。

    如果加到main_queue中,在主线程中添加任务操作,就会引起死锁。

    // e.g.

    dispatch_sync(dispatch_get_main_queue(),{()->Void in

    print("sync2")

    })


    暂停和继续执行队列

    func  dispatch_suspend() 暂停

    func dispatch_resume() 继续

    suspend  使 suspension reference count +1

    resume    -1

    count>0  queue就保持挂起状态

    如果挂起了  一个 queue   或者  source    那么销毁他之前,先对其进行恢复。

    var concurrentQueue = dispatch_queue_create("concurrentQueue_1",DISPATCH_QUEUE_CONCURRENT)

    // stop

    dispatch_suspend(concurrentQueue)

    // go on

    dispatch_resume(concurrentQueue)

    只执行一次 用于单例

    dispatch_once

    延时:指定时间后把任务追加到 dispatch queue里面

    dispatch_after

    func dispatch_time(when:XX,delta:Int64)->dispatch_time_t

    delta单位非常小,到秒要乘以  NSEC_PER_SEC

    let deltaT = 2.0 *Double(NSEC_PER_SEC)

    let  dTime =dispatch_time(DISPATCH_TIME_NOW,Int64(deltaT))

    dispatch_after(dTime,dispatch_get_global-global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0)

    {()->Viod in

    println("延时2秒执行")

    })

    多个任务都结束的一个全部结束:dispatch_barrier_async

    当执行任务更新数据时,会出现数据不一样的情况。

    for i in 1...100

    {

    dispatch_async(queue,{()->Void in

    println("(i)")

    })

    }

    虽然使用dispatch_barrier_async可以避免

    但是有另一方法,  semaphore 信号量

    var semaphore = dispatch_semaphore_creat(1)//初始值为1

    for i in 1...100

    {

    dispatch_async(queue,{()->Void in

    dispatch_semaphore_wait(semaphore,DISPATCH_TIME_FOREVER)

    println("(i)")

    dispatch_semaphore_signal(semaphore)

    })

    }

  • 相关阅读:
    深入理解.NET(第2版.英文影印版)书评
    揭示同步块索引(上):从lock开始
    【读书笔记】.NET本质论第一章 The CLR as a Better COM
    【翻译】TestAfter Development is not TestDriven Development
    【读书笔记】.NET本质论第二章Components(Part One)
    Python和Ruby:流行动态脚本语言之特点对比
    C++ Unit Testing Framework: A Boost Test Tutorial——part2:Using Boost Test
    组态软件开发(zz)
    用于实现拖入操作的通用类
    找到一个脚本引擎
  • 原文地址:https://www.cnblogs.com/heri/p/4579765.html
Copyright © 2020-2023  润新知