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)") } }
- Thread常用属性及方法示例
-
线程同步
线程同步方法通过锁来实现,每个线程都只用一个锁,这个锁与一个特定的线程关联。
-
- NSCondition
condition.lock() //加锁
condition.unlock() //解锁
condition.wait() //等待
condition.signal() //唤醒
- NSCondition
-
- 示例
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)
-
- 示例