Swift - NSThread线程相关简单说明

说明

1)关于多线程部分的理论知识和Swift实现。
2)该文仅仅简单讲解NSThread在Swift语境中的一些使用和注意点,别他。

NSThread的基本使用和创建

基本用法(主线程|当前线程)

        // 获得执行该方法的当前线程
        let currentThread = NSThread.currentThread
        // 当前线程为:(Function)
        print("当前线程为:\(currentThread)")
        
        // 获得应用程序的主线程
        let mainThread = NSThread.mainThread()
        // 应用程序的主线程:{number = 1, name = main}
        print("应用程序的主线程:\(mainThread)")
        
        // 判断当前线程是否是主线程
        let isMain = NSThread.isMainThread()
        print(isMain)  // return:true

创建线程

说明:此处列出创建线程的四种方法:分别是

直接创建|分离出一条子线程|创建一条后台线程|自定义线程类继承自NSThread重写内部的main方法封装任务,然后init创建。

    // NSThread创建线程的四种方式
    func createNewThreadWithNSThreadMethodOne() {
        // 创建线程
        let thread = NSThread.init(target: self, selector: Selector("run"), object: nil)
        // 设置线程的名称
        thread.name = "线程A"
        // 启动线程
        thread.start()
    }
    
    func createNewThreadWithNSThreadMethodTwo() {
        // 分离出一条子线程,自动启动线程,但无法获得线程对象
        NSThread.detachNewThreadSelector(Selector("run"), toTarget: self, withObject: nil)
    }
    
    func createNewThreadWithNSThreadMethodThree() {
        // 开启一条后台线程,自动启动线程,但无法获得线程对象
        self.performSelectorInBackground(Selector("run"), withObject: nil)
    }
    
    func createNewThreadWithNSThreadMethodFour() {
        let thread = CustomThread()
        thread.start()
        
    }
    
    func run() {
        // 获得当前执行run方法的线程
        let thread = NSThread.currentThread()
        print("run--\(thread.name)-\(thread)")
    }

NSThread线程的状态和线程安全

线程的状态

线程的状态:新建-就绪-运行-阻塞-死亡

        // 程的退出
        NSThread.exit()
        // 线程的休眠1
        NSThread.sleepForTimeInterval(2.0)
        // 线程的休眠2
        NSThread.sleepUntilDate(NSDate.init(timeIntervalSinceNow: 3.0))

线程安全

说明:多线程访问同一个资源的时候可能会出现数据错乱等安全问题,解决方法是对必要的代码段进行加锁。
注意:在OC中加互斥锁使用@synchronized(self) {},
在swift可以使用objc_sync_enter(self)和objc_sync_exit(self)方法,
注意这两个方法必须成对使用,把要加锁的代码放在中间

//
//  ViewController.swift
//  Programming in Swift
//
//  Created by ChenQianPing on 16/5/23.
//  Copyright © 2016年 ChenQianPing. All rights reserved.
//

import UIKit

class ViewController: UIViewController {
    
    // 设置总票数为100张
    var totalTickets = 100

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        
        // 多线程访问资源加锁
        // 创建三条线程分别代表售票员A、售票员B、售票员C
        let thread01 = NSThread.init(target: self, selector:Selector("saleTickect"), object: nil)
        let thread02 = NSThread.init(target: self, selector: Selector("saleTickect"), object: nil);
        let thread03 = NSThread.init(target: self, selector: Selector("saleTickect"), object: nil);
        
        // 设置线程的名称
        thread01.name = "售票员A"
        thread02.name = "售票员B"
        thread03.name = "售票员C"
        
        // 开启线程
        thread01.start()
        thread02.start()
        thread03.start()
        
    }
    
    // 模拟售票的函数
    func saleTickect() {
        while(true) {
            
            // 加互斥锁
            /* 
            * 1)同OC中的@synchronized(self) {}
            * 2)objc_sync_enter(self)和objc_sync_exit(self)必须成对使用,把要加锁的代码放在中间
            */
            objc_sync_enter(self)
            
            // 检查是否有余票,如果有则卖出去一张
            let temp = totalTickets
            for var i=0;i<100000;i++ {
                // 空的for循环,模拟延迟
            }
            if(temp > 0) {
                totalTickets = temp - 1
                print("\(NSThread.currentThread().name)卖出去了一张票,还剩\(totalTickets)")
            } else {
                print("\(NSThread.currentThread().name)发现票已经卖完了")
                break
            }
            objc_sync_exit(self)
        }
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }


}

Optional("售票员A")卖出去了一张票,还剩99
Optional("售票员B")卖出去了一张票,还剩98
Optional("售票员C")卖出去了一张票,还剩97
Optional("售票员A")卖出去了一张票,还剩96
Optional("售票员B")卖出去了一张票,还剩95
Optional("售票员C")卖出去了一张票,还剩94
Optional("售票员A")卖出去了一张票,还剩93
Optional("售票员B")卖出去了一张票,还剩92
Optional("售票员C")卖出去了一张票,还剩91
Optional("售票员A")卖出去了一张票,还剩90
Optional("售票员B")卖出去了一张票,还剩89
Optional("售票员C")卖出去了一张票,还剩88
Optional("售票员A")卖出去了一张票,还剩87
Optional("售票员B")卖出去了一张票,还剩86
Optional("售票员C")卖出去了一张票,还剩85
Optional("售票员A")卖出去了一张票,还剩84
Optional("售票员B")卖出去了一张票,还剩83
Optional("售票员C")卖出去了一张票,还剩82
Optional("售票员A")卖出去了一张票,还剩81
Optional("售票员B")卖出去了一张票,还剩80
Optional("售票员C")卖出去了一张票,还剩79
Optional("售票员A")卖出去了一张票,还剩78
Optional("售票员B")卖出去了一张票,还剩77
Optional("售票员C")卖出去了一张票,还剩76
Optional("售票员A")卖出去了一张票,还剩75
Optional("售票员B")卖出去了一张票,还剩74
Optional("售票员C")卖出去了一张票,还剩73
Optional("售票员A")卖出去了一张票,还剩72
Optional("售票员B")卖出去了一张票,还剩71
Optional("售票员C")卖出去了一张票,还剩70
Optional("售票员A")卖出去了一张票,还剩69
Optional("售票员B")卖出去了一张票,还剩68
Optional("售票员C")卖出去了一张票,还剩67
Optional("售票员A")卖出去了一张票,还剩66
Optional("售票员B")卖出去了一张票,还剩65
Optional("售票员C")卖出去了一张票,还剩64
Optional("售票员A")卖出去了一张票,还剩63
Optional("售票员B")卖出去了一张票,还剩62
Optional("售票员C")卖出去了一张票,还剩61
Optional("售票员A")卖出去了一张票,还剩60
Optional("售票员B")卖出去了一张票,还剩59
Optional("售票员C")卖出去了一张票,还剩58
Optional("售票员A")卖出去了一张票,还剩57
Optional("售票员B")卖出去了一张票,还剩56
Optional("售票员C")卖出去了一张票,还剩55
Optional("售票员A")卖出去了一张票,还剩54
Optional("售票员B")卖出去了一张票,还剩53
Optional("售票员C")卖出去了一张票,还剩52
Optional("售票员A")卖出去了一张票,还剩51
Optional("售票员B")卖出去了一张票,还剩50
Optional("售票员C")卖出去了一张票,还剩49
Optional("售票员A")卖出去了一张票,还剩48
Optional("售票员B")卖出去了一张票,还剩47
Optional("售票员C")卖出去了一张票,还剩46
Optional("售票员A")卖出去了一张票,还剩45
Optional("售票员B")卖出去了一张票,还剩44
Optional("售票员C")卖出去了一张票,还剩43
Optional("售票员A")卖出去了一张票,还剩42
Optional("售票员B")卖出去了一张票,还剩41
Optional("售票员C")卖出去了一张票,还剩40
Optional("售票员A")卖出去了一张票,还剩39
Optional("售票员B")卖出去了一张票,还剩38
Optional("售票员C")卖出去了一张票,还剩37
Optional("售票员A")卖出去了一张票,还剩36
Optional("售票员B")卖出去了一张票,还剩35
Optional("售票员C")卖出去了一张票,还剩34
Optional("售票员A")卖出去了一张票,还剩33
Optional("售票员B")卖出去了一张票,还剩32
Optional("售票员C")卖出去了一张票,还剩31
Optional("售票员A")卖出去了一张票,还剩30
Optional("售票员B")卖出去了一张票,还剩29
Optional("售票员C")卖出去了一张票,还剩28
Optional("售票员A")卖出去了一张票,还剩27
Optional("售票员B")卖出去了一张票,还剩26
Optional("售票员C")卖出去了一张票,还剩25
Optional("售票员A")卖出去了一张票,还剩24
Optional("售票员B")卖出去了一张票,还剩23
Optional("售票员C")卖出去了一张票,还剩22
Optional("售票员A")卖出去了一张票,还剩21
Optional("售票员B")卖出去了一张票,还剩20
Optional("售票员C")卖出去了一张票,还剩19
Optional("售票员A")卖出去了一张票,还剩18
Optional("售票员B")卖出去了一张票,还剩17
Optional("售票员C")卖出去了一张票,还剩16
Optional("售票员A")卖出去了一张票,还剩15
Optional("售票员B")卖出去了一张票,还剩14
Optional("售票员C")卖出去了一张票,还剩13
Optional("售票员A")卖出去了一张票,还剩12
Optional("售票员B")卖出去了一张票,还剩11
Optional("售票员C")卖出去了一张票,还剩10
Optional("售票员A")卖出去了一张票,还剩9
Optional("售票员B")卖出去了一张票,还剩8
Optional("售票员C")卖出去了一张票,还剩7
Optional("售票员A")卖出去了一张票,还剩6
Optional("售票员B")卖出去了一张票,还剩5
Optional("售票员C")卖出去了一张票,还剩4
Optional("售票员A")卖出去了一张票,还剩3
Optional("售票员B")卖出去了一张票,还剩2
Optional("售票员C")卖出去了一张票,还剩1
Optional("售票员A")卖出去了一张票,还剩0
Optional("售票员B")发现票已经卖完了

NSThread线程间通信

说明

所谓线程间通信,即如何从一个线程进入到另一个线程继续执行任务或者是传递参数(如从子线程回到主线程)

下面的代码示例演示在主线程中先创建一个子线程下载图片,当图片下载完成后又切换到主线程设置图片的操作。

import UIKit

class ViewController: UIViewController {
    
    @IBOutlet weak var imageView: UIImageView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        
        // 程序启动后开子线程下载图片,图片下载完成之后回到主线程设置图片
        NSThread.detachNewThreadSelector(Selector("downloadImage"), toTarget: self, withObject: nil)
        
    }
    
    func downloadImage() {
        // 获得要下载图片的url
        let url = NSURL.init(string: "http://cdn.cocimg.com/assets/images/logo.png")
        // 把url地址指向资源的二进制下载到本地
        let imageData = NSData.init(contentsOfURL: url!)
        // 把二进制数据转换为图片
        let image = UIImage.init(data: imageData!)
        
        // 打印查看当前线程(应该是在子线程中下载图片)
        print("当前线程为\(NSThread.currentThread())")

        // 线程间通信
        self.performSelectorOnMainThread(Selector("showImage:"), withObject: image, waitUntilDone:true)
        
    }
    
    func showImage(image:UIImage) {
        imageView.image = image
        print("处理UI刷新操作的线程:\(NSThread.currentThread())")
    }
    
  
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }


}

当前线程为{number = 2, name = (null)}
处理UI刷新操作的线程:{number = 1, name = main}

你可能感兴趣的:(Swift - NSThread线程相关简单说明)