字符串分割的三种方法 & 凭什么GCD比NSOperat
字符串分割的三种方法
var string = " Lorem ipsum dolar sit amet。你好,我的名字叫\"honzon\" "
string = string.stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceCharacterSet())
print("第一种")
var components: NSArray = string.componentsSeparatedByCharactersInSet(NSCharacterSet.whitespaceCharacterSet())
components = components.filteredArrayUsingPredicate(NSPredicate(format: "self <> ''"))
string = components.componentsJoinedByString(" ")
print(string)
print("\n第二种")
let cfString = string as CFString
let locale = CFLocaleCopyCurrent()
let tokenizer = CFStringTokenizerCreate(kCFAllocatorDefault, cfString, CFRangeMake(0, CFStringGetLength(cfString)), kCFStringTokenizerUnitWord, locale)
//通过CFOptionFlags来分割
while CFStringTokenizerAdvanceToNextToken(tokenizer) != .None {
let tokenRange = CFStringTokenizerGetCurrentTokenRange(tokenizer)
let tokenValue = CFStringCreateWithSubstring(kCFAllocatorDefault, cfString, tokenRange)
CFShow(tokenValue)
}
print("\n第三种")
let range = Range(start: string.startIndex, end: string.endIndex)
string.enumerateSubstringsInRange(range, options: .ByWords) { (substring, substringRange, enclosingRange, stop) -> () in
print(substring!)
if substring == "你" {stop = true}
}
打印结果:
第一种
Lorem ipsum dolar sit amet。你好,我的名字叫"honzon"
第二种
Lorem
ipsum
dolar
sit
amet
\u4f60
\u597d
\u6211
\u7684
\u540d\u5b57
\u53eb
honzon
第三种
Lorem
ipsum
dolar
sit
amet
你
参考网址:
How to get an array of sentences using CFStringTokenizer?
凭什么GCD比NSOperationQueue效率更高
NSOperation
是对GCD面向对象的ObjC封装,可以控制线程(开始,取消,优先级等),线程依赖关系以及监听任务完成状态。但是,在没有依赖其他NSOperation
的情况下,每当向NSOperationQueue
中添加一个NSOperation
,系统就会开辟一个新线程来处理这个NSOperation
.
func printThreadMessage(items: Any...) -> Void {
Swift.print(items,NSThread.mainThread(), NSThread.currentThread(),"\n")
}
class HonzonRequest: NSObject{
static let sharedInstance: HonzonRequest = {
let hzRequest = HonzonRequest()
hzRequest.queue.maxConcurrentOperationCount = 5
return hzRequest
}()
let queue = NSOperationQueue()
}
然后我们自定一个HZOperation
,也可以使用NSBlockOperation
,是一样的效果
注意:
NSInvocationOperation
is unavailable in Swift
NSInvocationOperation
is unavailable in Swift
NSInvocationOperation
is unavailable in Swift
//MARK: HZOperation
//
//NSOperation本身是抽象基类 因此必须使用它的子类或者自定义
// 1.使用自己定义的同步operation,需要继承自NSOperation,并实现必要的方法:isFinished(Swift 为finished属性),isExecuting(Swift 为executing属性),main等,并实现KVO机制
// 2.如果不想让你自定义的operation与其他operation进行异步操作,你可以手动开始(调用start方法),并且在operation的start方法里面简单的调用main方法。
// 3.如果要自定义operation,需要继承资NSOperation。并且重载 isExecuting(Swift 为executing属性)方法和isFinished(Swift 为finished属性)方法。在这两个方法中,必须返回一个线程安全值(通常是个BOOL值),这个值可以在 operation 中进行操作。
// 4.一旦你的 operation 开始了,必须通过 KVO,告诉所有的监听者,现在该operation的执行状态。
// 5.在 operation 的 main 方法里面,必须提供 autorelease pool,因为你的 operation 完成后需要销毁。
// 6.为我们自定义的 operation 提供一个初始化方法。如:init(_ workBlock: () ->Void) 方法。
class HZOperation: NSOperation {
private var finish = false
private var execut = false
let block: (() ->Void)?
override var finished: Bool {
return finish
}
override var executing: Bool {
return execut
}
override var asynchronous: Bool {
return false
}
override init() {
self.block = nil
}
init(_ workBlock: () ->Void) {
self.block = workBlock
}
override func main() {
autoreleasepool {
if self.cancelled {return}
if self.finished {return}
var taskIsFinished = false
while taskIsFinished == false && self.cancelled == false {
//coding
self.block!()
taskIsFinished = true
}
self.willChangeValueForKey("finished")
self.willChangeValueForKey("executing")
finish = true
execut = false
self.didChangeValueForKey("finish")
self.didChangeValueForKey("executing")
}
}
//一般不推荐重写start方法 重写main()函数即可
// override func start() {
// if self.cancelled {
// self.willChangeValueForKey("finished")
// //coding
// finish = true
// self.didChangeValueForKey("finished")
// return;
// } else {
// self.willChangeValueForKey("executing")
// //coding
// execut = true
// self.main()
// self.didChangeValueForKey("executing")
// }
// }
}
测试代码如下:
class func hzTestOperation() {
let operation = HZOperation {
printThreadMessage("HZOperation: operation")
}
let operation1 = HZOperation {
printThreadMessage("HZOperation: operation1")
}
let operation2 = HZOperation {
printThreadMessage("HZOperation: operation2")
}
let operation3 = HZOperation {
printThreadMessage("HZOperation: operation3")
}
operation.addDependency(operation3)
HonzonRequest.sharedInstance.queue.addOperation(operation)
HonzonRequest.sharedInstance.queue.addOperation(operation1)
HonzonRequest.sharedInstance.queue.addOperation(operation2)
HonzonRequest.sharedInstance.queue.addOperation(operation3)
}
打印结果:
["hzSyncOperation: operation2"] <NSThread: 0x7f81d9409dc0>{number = 1, name = (null)} <NSThread: 0x7f81d958c4e0>{number = 2, name = (null)}
["hzSyncOperation: operation1"] <NSThread: 0x7f81d9409dc0>{number = 1, name = (null)} <NSThread: 0x7f81d9613520>{number = 4, name = (null)}
["hzSyncOperation: operation3"] <NSThread: 0x7f81d9409dc0>{number = 1, name = (null)} <NSThread: 0x7f81d9444f40>{number = 3, name = (null)}
["hzSyncOperation: operation"] <NSThread: 0x7f81d9409dc0>{number = 1, name = (null)} <NSThread: 0x7f81d9444f40>{number = 3, name = (null)}
从结果可以知道,在没有依赖其他NSOperation
的情况下,operation2, operation1, operation3
都是开辟的新线程来处理,而operation
是依赖于operation3
,于是在operation3
完成之后,就直接复用了处理operation3
的线程。
GCD
是一个低级别的基于C语言的API,这是GCD效率高于NSOperationQueue的一个原因,而我认为最重要的原因还是Gotchas With Grand Central Dispatch (libdispatch) And Blocks 中提到的Every time a queue wants to run a block, GCD tries to reuse a thread that has finished running a block and is now doing nothing. However, if all the threads are busy running their blocks then GCD will create a new thread for you.
测试代码如下:
class func hzGroupGCD() {
let group = dispatch_group_create()
let queue = dispatch_queue_create("hzThreadQueue", DISPATCH_QUEUE_CONCURRENT)
dispatch_group_async(group, queue) {
printThreadMessage("hzGroup: First task")
}
dispatch_group_async(group, queue) {
printThreadMessage("hzGroup: Secound task")
}
dispatch_group_async(group, queue) {
printThreadMessage("hzGroup: Third task")
}
dispatch_group_notify(group, queue) {
printThreadMessage("hzGroup: All tasks completion")
}
}
//控制最大并发数
class func hzSemaphoreConcurrentGCD() {
let group = dispatch_group_create()
let semaphore = dispatch_semaphore_create(2)
let queue = dispatch_queue_create("hzThreadQueue", DISPATCH_QUEUE_CONCURRENT)
for i in 0..<10 {
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER)
dispatch_group_async(group, queue, {
printThreadMessage("hzGroup: \(i) task completion")
sleep(2)
dispatch_semaphore_signal(semaphore)
})
}
dispatch_group_wait(group, DISPATCH_TIME_FOREVER)
}
hzGroupGCD()
打印结果如下:
["hzGroup: First task"] <NSThread: 0x7fc9f9508c40>{number = 1, name = (null)} <NSThread: 0x7fc9f9406c80>{number = 2, name = (null)}
["hzGroup: Secound task"] <NSThread: 0x7fc9f9508c40>{number = 1, name = (null)} <NSThread: 0x7fc9f9712250>{number = 4, name = (null)}
["hzGroup: Third task"] <NSThread: 0x7fc9f9508c40>{number = 1, name = (null)} <NSThread: 0x7fc9f940b5b0>{number = 3, name = (null)}
["hzGroup: All tasks completion"] <NSThread: 0x7fc9f9508c40>{number = 1, name = (null)} <NSThread: 0x7fc9f940b5b0>{number = 3, name = (null)}
可以清楚的看到所有任务完成之后的事件处理是直接复用的处理最后一个完成任务的线程
hzSemaphoreConcurrentGCD()
打印结果如下:
["hzGroup: 0 task completion"] <NSThread: 0x7fd1da604af0>{number = 1, name = (null)} <NSThread: 0x7fd1da412380>{number = 2, name = (null)}
["hzGroup: 1 task completion"] <NSThread: 0x7fd1da604af0>{number = 1, name = (null)} <NSThread: 0x7fd1da7133b0>{number = 3, name = (null)}
["hzGroup: 2 task completion"] <NSThread: 0x7fd1da604af0>{number = 1, name = (null)} <NSThread: 0x7fd1da7133b0>{number = 3, name = (null)}
["hzGroup: 3 task completion"] <NSThread: 0x7fd1da604af0>{number = 1, name = (null)} <NSThread: 0x7fd1da412380>{number = 2, name = (null)}
["hzGroup: 4 task completion"] <NSThread: 0x7fd1da604af0>{number = 1, name = (null)} <NSThread: 0x7fd1da412380>{number = 2, name = (null)}
["hzGroup: 5 task completion"] <NSThread: 0x7fd1da604af0>{number = 1, name = (null)} <NSThread: 0x7fd1da7133b0>{number = 3, name = (null)}
["hzGroup: 6 task completion"] <NSThread: 0x7fd1da604af0>{number = 1, name = (null)} <NSThread: 0x7fd1da412380>{number = 2, name = (null)}
["hzGroup: 7 task completion"] <NSThread: 0x7fd1da604af0>{number = 1, name = (null)} <NSThread: 0x7fd1da7133b0>{number = 3, name = (null)}
["hzGroup: 8 task completion"] <NSThread: 0x7fd1da604af0>{number = 1, name = (null)} <NSThread: 0x7fd1da412380>{number = 2, name = (null)}
["hzGroup: 9 task completion"] <NSThread: 0x7fd1da604af0>{number = 1, name = (null)} <NSThread: 0x7fd1da7133b0>{number = 3, name = (null)}
基本上,都是在复用2个线程,而没有开辟新的线程来处理新的任务。GCD
的这个机制保证了GCD
的效率远远高于NSOperationQueue
结论:
在没有依赖其他
NSOperation
的情况下,每当向NSOperationQueue
中添加一个NSOperation
,就会开辟一个新线程
来处理这个NSOperation
GCD会维护一个线程的复用,只有当其他线程都不空闲时,GCD才会创建一个新的线程
参考网址:
Gotchas With Grand Central Dispatch (libdispatch) And Blocks
因为学习Swift时间并不长,所以某些地方可能有误,如果发现,请及时告知。
本文为原创文章,未经本人同意,禁止转载