iOS 线程保活


JXPermenantThread

子线程保活:

快速创建子线程,让子线程一直存活,并提供执行任务的block,直到CHGPermenantThread对象销毁或者主动调用stop。

应用场景:

在实际开发中经常会遇到一些耗时,且需要频繁处理的工作,这部分工作与UI无 关,比如说大文件的下载,后台间隔一段时间进行数据的上报,APM中开启一个watch dog线程等。

注意只适用于非并发

调用方式

 // 创建一个保活线程,直到ViewController销毁,或者主动调用stop
var thread = JXPermenantThread()

hread.execute {
           [weak self] in
           print("执行任务 - %@", Thread.current)
 }
   
 // 主动销毁该子线程
thread.stop()

实现代码

    import UIKit

    typealias JXPermenantThreadTask = ()-> Void
    ///线程保活 使用runloop
    class JXPermenantThread: NSObject {
    private class BlockWrapper: NSObject {
        var block: ()->Void
        init(block: @escaping ()->Void) {
            self.block = block
        }
    }
    
    private var thread: Thread?
    private var isStopped = false
    
    override init() {
        super.init()
        let thread = Thread { [weak self] in
            //如果RunLoop Mode里没有任何Source0/Source1/Timer/Observer,RunLoop会立马退出,需要添加添加port监听

            RunLoop.current.add(Port(), forMode: .default)
            // self没有被释放,并且线程没有被stop,不能添加guard let self = self else {return}为什么?
            while !(self?.isStopped ?? true) {
                RunLoop.current.run(mode: .default, before: .distantFuture)
            }
        }
        thread.start()
        self.thread = thread
    }
    
    func stop() {
        if let thread = thread, !isStopped {
            perform(#selector(innerStop), on: thread, with: nil, waitUntilDone: true)
        }
    }
    
    func execute(task: @escaping JXPermenantThreadTask) {
        if let thread = thread {
            //注意block必须要通过class包起来,否则RunLoop.current.run(mode: .default, before: .distantFuture)会崩溃
            let inner = BlockWrapper(block: task)
            perform(#selector(innerExecute(_:)), on: thread, with: inner, waitUntilDone: false)
        }
    }
    
    @objc private func innerStop() {
        isStopped = true
        // 停掉子线程的RunLoop
        CFRunLoopStop(CFRunLoopGetCurrent())
        thread = nil
    }
    
    @objc private func innerExecute(_ inner: BlockWrapper) {
        inner.block()
    }
    
    deinit {
        stop()
        debugPrint("PermenantThread2 deinit")
    }
}

参照的文章:

  • 线程保活
  • 面试题-线程保活

你可能感兴趣的:(iOS 线程保活)