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")
}
}
参照的文章:
网友评论