swift学习之多线程(一)Thread

一,多线程的优缺点

  • 优点:能适当提高程序的执行效率,能适当提高资源利用率(CPU,内存)
  • 缺点:线程越多,CPU在调度线程上的开销就越大,线程之间的通信、多线程的数据共享更复杂

二,Swift多线程编程方案: 

  Swift继续使用Object-C原有的一套线程,包括三种多线程编程技术:

三、NSThread

  NSThread 比其他两个轻量级,但是需要自己管理线程的生命周期,线程同步。线程同步对数据的加锁会有一定的系统开销

  • Thread的创建

    • 类方法创建线程并且开始运行线程 (无法对线程进行更详细的设置)

      API:

      @available(iOS 10.0, *)
      open class func detachNewThread(_ block: @escaping () -> Void)

      open class func detachNewThreadSelector(_ selector: Selector, toTarget target: Any, with argument: Any?)

      示例:

      class ViewController: UIViewController {
          override func viewDidLoad() {
              super.viewDidLoad()
              //MARK:使用类方法
              ///方法一
              Thread.detachNewThreadSelector(#selector(threadMethods1), toTarget:self, with: nil)
              ///方法二
              Thread.detachNewThread {
                  print("通过闭包形式")
                  print("\(#function):\(Thread.current)")
              }
          }
      
          //MARK:Target Methods
          @objc private func threadMethods1() {
              print("通过方法形式")
              print("\(#function):\(Thread.current)")
          }
      }
    • 实例方法创建线程(操作前可以设置线程的优先级,名称等属性)

      API:

      @available(iOS 2.0, *)
      public convenience init(target: Any, selector: Selector, object argument: Any?)

      @available(iOS 10.0, *)
      public convenience init(block: @escaping () -> Void)

      示例:
      class ViewController: UIViewController {
          override func viewDidLoad() {
              super.viewDidLoad()
              //MARK:使用实例方法
              ///方法一
              let thread1 = Thread(target: self, selector: #selector(threadMethods1), object: nil)
              thread1.name = "thread1"
              thread1.threadPriority = 0.5 ///优先级
              thread1.start()
              ///方法二
              let thread2 = Thread{
                  print("通过闭包形式")
                  print("\(#function):\(Thread.current)")
              }
              thread1.name = "thread2"
              thread1.threadPriority = 1 ///优先级
              thread2.start()
          }
      
          //MARK:Target Methods
          @objc private func threadMethods1() {
              print("通过方法形式")
              print("\(#function):\(Thread.current)")
          }
      }
    • 隐式创建并启动线程

      API:

      extension NSObject {
         open func performSelector(onMainThread aSelector: Selector, with arg: Any?, waitUntilDone wait: Bool, modes array: [String]?)            
         open func performSelector(onMainThread aSelector: Selector, with arg: Any?, waitUntilDone wait: Bool)
      
         @available(iOS 2.0, *)
         open func perform(_ aSelector: Selector, on thr: Thread, with arg: Any?, waitUntilDone wait: Bool, modes array: [String]?)
      
         @available(iOS 2.0, *)
         open func perform(_ aSelector: Selector, on thr: Thread, with arg: Any?, waitUntilDone wait: Bool)
      
         @available(iOS 2.0, *)
         open func performSelector(inBackground aSelector: Selector, with arg: Any?)
      }
      示例:
      class ViewController: UIViewController {
          override func viewDidLoad() {
              super.viewDidLoad()
              //MARK:使用NSObject拓展方法
              ///在后台执行
              self.performSelector(inBackground:#selector(threadMethods1), with: nil)
              ///在主线程执行
              self.performSelector(onMainThread: #selector(threadMethods1), with: nil, waitUntilDone: false)
          }
      
          //MARK:Target Methods
          @objc private func threadMethods1() {
              print("通过方法形式")
              print("\(#function):\(Thread.current)")
          }
      }
  • Thread常用属性及方法

    • 属性:  

      ///您可以使用返回的字典来存储特定于线程的数据。在对NSThread对象进行任何操作时都不会使用线程字典——它只是一个可以存储任何感兴趣数据的地方。
      ///例如,Foundation使用它来存储线程的默认NSConnection和NSAssertionHandler实例。您可以为字典定义自己的键。
      open var threadDictionary: NSMutableDictionary { get }
       
      ///线程优先级,取值范围0.0~1.0,默认0.5,值越高优先级越高。
      @available(iOS 4.0, *)
      open var threadPriority: Double
      
      ///返回当前线程对象。
      open class var current: Thread { get }
      
      ///一个包含调用堆栈返回地址的数组。每个元素都是一个包含NSUInteger值的NSNumber对象。
      @available(iOS 2.0, *)
      open class var callStackReturnAddresses: [NSNumber] { get }
      
      ///返回值描述了调用此方法时当前线程的调用堆栈回溯。
      @available(iOS 4.0, *)
      open class var callStackSymbols: [String] { get }
      
      ///线程名称。
      @available(iOS 2.0, *)
      open var name: String?
      
      ///设置堆栈大小(这个值必须以字节为单位,并且是4KB的倍数。)
      @available(iOS 2.0, *)
      open var stackSize: Int
      
      ///当前线程是否为主线程。
      @available(iOS 2.0, *)
      open var isMainThread: Bool { get }
      
      ///线程是否为主线程。
      @available(iOS 2.0, *)
      open class var isMainThread: Bool { get }
      
      ///返回主线程对象。
      @available(iOS 2.0, *)
      open class var main: Thread { get }
      
      ///线程是否正在执行。
      @available(iOS 2.0, *)
      open var isExecuting: Bool { get }
      
      ///线程是否已经结束。
      @available(iOS 2.0, *)
      open var isFinished: Bool { get }
      
      ///线程是否已标记为取消。
      @available(iOS 2.0, *)
      open var isCancelled: Bool { get }
    • 方法
      ///是否是多线程
      open class func isMultiThreaded() -> Bool
              
      ///线程阻塞到某一时间。
      open class func sleep(until date: Date)
              
      ///线程阻塞一段时间。
      open class func sleep(forTimeInterval ti: TimeInterval)
              
      ///退出当前线程,不可在主线程调用,否则程序崩溃
      open class func exit()
              
      ///获取线程优先级。
      open class func threadPriority() -> Double
              
      ///设置线程优先级,取值范围0.0~1.0,默认0.5,值越高优先级越高。
      open class func setThreadPriority(_ p: Double) -> Bool
              
      ///将线程标记为取消状态。
      @available(iOS 2.0, *)
      open func cancel()
              
      ///开启线程。
      @available(iOS 2.0, *)
      open func start(
    • Thread常用属性及方法示例
      class ViewController: UIViewController {
          var myThread:Thread?
          override func viewDidLoad() {
              super.viewDidLoad()
              ///设置主线程
              Thread.main.name = "MainThread"
              threadMethods1()
          }
          
          //MARK:Target Methods
          private func threadMethods1() {
              myThread = Thread(target: self, selector: #selector(myThreadMethods), object: nil)
              myThread!.name = "MyThread"
              myThread!.threadPriority = 1.0
              myThread!.start()
              
              ///主线程阻塞
              Thread.sleep(forTimeInterval: 3)
              ///打印子线程运行状态
              print("3 seconds later, myThread is executing :  \(myThread!.isExecuting)")
              print("3 seconds later, myThread is finished :  \(myThread!.isFinished)")
          }
          
          ///响应事件
          @objc private func myThreadMethods(){
              ///打印主线程
              print("Main thread is :\(Thread.main)")
              ///打印当前线程
              print("Current thread is :\(Thread.current)")
              ///判断当前线程是否是主线程
              print("Current thread is main thread:\(Thread.isMainThread)")
              
              // 打印子线程名称
              print("myThread name is :  \(String(describing: myThread!.name))")
              // 打印子线程优先级
              print("myThread priority is :  \(myThread!.threadPriority)")
              // 打印子线程是否是主线程
              print("myThread is main thread :  \(myThread!.isMainThread)")
              // 子线程是否正在执行
              print("myThread is executing :  \(myThread!.isExecuting)")
              // 子线程是否标记取消
              print("myThread is cancelled :  \(myThread!.isCancelled)")
              // 子线程是否已经结束。
              print("myThread is finished :  \(myThread!.isFinished)")
          }
      } 
  • 线程同步

    线程同步方法通过锁来实现,每个线程都只用一个锁,这个锁与一个特定的线程关联。
    • NSCondition
      condition.lock()       //加锁
      condition.unlock()    //解锁
      condition.wait()       //等待
      condition.signal()     //唤醒
    • 示例
      class ViewController: UIViewController {
          /// 定义线程及线程条件,用于锁住线程
          /// 线程一
          var thread1:Thread?
          let condition1 = NSCondition()
          /// 线程二
          var thread2:Thread?
          let condition2 = NSCondition()
          
          override func viewDidLoad() {
              super.viewDidLoad()
              thread2 = Thread(target: self, selector: #selector(ViewController.method2),object: nil)
              thread1 = Thread(target: self, selector: #selector(ViewController.method1),object: nil)
              thread1?.start()
          }
          
          ///定义两方法,用于两个线程调用
          ///方法一
          @objc func method1(sender:AnyObject){
              for i in 0 ..< 10 {
                  print("Thread 1 running \(i)")
                  sleep(1)
      
                  if i == 2 {
                      thread2?.start() //启动线程2
                      //本线程(thread1)锁定
                      condition1.lock()
                      condition1.wait()
                      condition1.unlock()
                  }
              }
              
              print("Thread 1 over")
              //线程2激活
              condition2.signal()
          }
          
          ///方法二
          @objc func method2(sender:AnyObject){
              for i in 0 ..< 10 {
                  print("Thread 2 running \(i)")
                  sleep(1)
                  
                  if i == 2 {
                      //线程1激活
                      condition1.signal()
                      //本线程(thread2)锁定
                      condition2.lock()
                      condition2.wait()
                      condition2.unlock()
                  }
              }
              print("Thread 2 over")
          }
      }
    • NSLock            

      • oc中的互斥锁:

        @synchronized(self) {

           //需要执行的代码块

         }           

      • swift中的互斥锁:

        objc_sync_enter(self)

        //需要执行的代码块

        objc_sync_exit(self)

         

posted on 2021-07-20 18:31  梁飞宇  阅读(1460)  评论(0编辑  收藏  举报