字符串分割的三种方法 & 凭什么GCD比NSOperat

2016-03-31  本文已影响335人  honzon_0

字符串分割的三种方法

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
你

参考网址:

NSCharacter​Set

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才会创建一个新的线程

参考网址:

继承NSOperation-自定义同步 operation

iOS开发系列--并行开发其实很容易

Gotchas With Grand Central Dispatch (libdispatch) And Blocks

因为学习Swift时间并不长,所以某些地方可能有误,如果发现,请及时告知。

本文为原创文章,未经本人同意,禁止转载

上一篇下一篇

猜你喜欢

热点阅读