前一篇文章《iOS开机广告实现》里面第二种获取广告数据的方法有一个困难需要克服,就是如果在主线程睡眠时间内,子线程已经下载好广告数据,这时要主动唤醒主线程,也就是线程唤醒的问题。
对于线程问题,网上大部分都是开辟子线程及线程睡眠的文章,却几乎没有如何手动唤醒线程的文章。最终,在一篇博客里面看到了一种解决方案,那就是NSCondition。
NSCondition
NSCondition的方法很少,只有如下的几个:
@available(iOS 2.0, *)
public class NSCondition : NSObject, NSLocking {
public func wait()
public func waitUntilDate(limit: NSDate) -> Bool
public func signal()
public func broadcast()
@available(iOS 2.0, *)
public var name: String?
}
通过wait()
和waitUntilDate(limit: NSDate) -> Bool
这两个方法都可以实现线程阻塞即线程睡眠,不同之处在于wait()
会使线程一直处于休眠状态,直到收到signal()
为止;而waitUntilDate(limit: NSDate) -> Bool
在使线程睡眠的同时会设置睡眠的终止时间,如果在终止时间前收到了signal()
就会唤醒线程;当到达终止时间的时候,即使没有收到signal()
,也会直接唤醒线程,而不会像wait()
方法那样一直睡眠下去。相关代码如下所示:
/// 阻塞线程获取广告信息
private var condition = NSCondition()
/// 获取广告信息总时间(程序阻塞最长时间)
private var totalTimeForGettingAd: Double = 6
//MARK: - 阻塞及唤醒
//阻塞当前线程
func blockedCurrentThread() {
//阻塞线程,如果规定时间内还未完成获取,则继续
let finalDate = NSDate(timeIntervalSinceNow: totalTimeForGettingAd)
condition.lock()
condition.waitUntilDate(finalDate)
condition.unlock()
}
//唤醒阻塞的线程,与blockedCurrentThread配套使用
func invokeThread() {
condition.lock()
condition.signal()
condition.unlock()
}