使用场景:
如果一个操作需要在子线程操作,串行,非并发。如果按照之前的逻辑,可能触发的时候就需要创建一个子线程,操作,然后线程销毁,下次操作again。
每次操作都开启一个线程,这样是很耗费性能的,为了节省性能,可以考虑对一个线程保活操作,要干活的时候,把任务扔给这个线程。不用的时候停止。比如频繁的写入日志文件的操作。
方式一:OC版本
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface PermanentThread : NSObject
/// 在常驻线程中执行动作
/// @param task block中的内容是在常驻线程中执行的行为
- (void)executeTask:(void (^)(void))task;
/// 停止常驻线程
- (void)stop;
@end
NS_ASSUME_NONNULL_END
#import "PermanentThread.h"
@interface PermanentThread()
@property (nonatomic, strong) NSThread *currentThread;
@property (nonatomic, assign) BOOL isStopped;
@end
@implementation PermanentThread
- (void)dealloc {
[self stop];
NSLog(@"%s",__func__);
}
- (instancetype)init {
self = [super init];
if (self) {
__weak typeof(self) weakSelf = self;
self.currentThread = [[NSThread alloc] initWithBlock:^{
// 往RunLoop中添加Source/Timers/Observers
[[NSRunLoop currentRunLoop] addPort:[[NSPort alloc] init] forMode:NSDefaultRunLoopMode];
// 其中的一次Loop结束后,下次进来条件成立,继续
while (weakSelf && !weakSelf.isStopped) {
// 启动RunLoop
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
}
}];
// 线程启动
[self.currentThread start];
}
return self;
}
/// 在常驻线程中执行动作
/// @param task block中的内容是在常驻线程中执行的行为
- (void)executeTask:(void (^)(void))task {
if (!self.currentThread || !task) {
return;
}
// 去子线程执行方法
[self performSelector:@selector(threadExecuteTask:) onThread:self.currentThread withObject:task waitUntilDone:NO];
}
/// 停止常驻线程
- (void)stop {
if (!self.currentThread) return;
/* 去子线程停止RunLoop
* waitUntilDone=YES,表示当前方法执行完毕后再执行别的
*/
[self performSelector:@selector(stopThread) onThread:self.currentThread withObject:nil waitUntilDone:YES];
}
/// 在线程中执行内容
/// @param task 内容
- (void)threadExecuteTask:(void (^)(void))task {
task();
}
/// 停止线程
- (void)stopThread {
// 标识设置成YES
self.isStopped = YES;
// 停止当前线程对应的Runloop
CFRunLoopStop(CFRunLoopGetCurrent());
self.currentThread = nil;
}
@end
OC版本使用:
#import "AViewController.h"
#import "PermanentThread.h"
@interface AViewController ()
@property (nonatomic, strong) PermanentThread *thread;
@end
@implementation AViewController
- (void)dealloc {
NSLog(@"%s",__func__);
}
- (void)viewDidLoad {
[super viewDidLoad];
self.thread = [[PermanentThread alloc] init];
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
__weak typeof(self) weakSelf = self;
[self.thread executeTask:^{
[weakSelf printSomething];
}];
NSLog(@"点击了界面");
}
// 点击了停止按钮
- (IBAction)clickStop {
[self.thread stop];
}
- (void)printSomething {
// sleep(3);
NSLog(@"当前的线程是 -- %@",[NSThread currentThread]);
}
@end
点击了界面
当前的线程是 -- <NSThread: 0x6000025290c0>{number = 6, name = (null)}
点击了界面
当前的线程是 -- <NSThread: 0x6000025290c0>{number = 6, name = (null)}
点击了界面
当前的线程是 -- <NSThread: 0x6000025290c0>{number = 6, name = (null)}
方式二:C语言版本
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface PermanentCThread : NSObject
/// 在常驻线程中执行动作
/// @param task block中的内容是在常驻线程中执行的行为
- (void)executeTask:(void (^)(void))task;
/// 停止常驻线程
- (void)stop;
@end
NS_ASSUME_NONNULL_END
#import "PermanentCThread.h"
@interface PermanentCThread()
@property (nonatomic, strong) NSThread *currentThread;
//@property (nonatomic, assign) BOOL isStopped;
@end
@implementation PermanentCThread
- (void)dealloc {
[self stop];
NSLog(@"%s",__func__);
}
- (instancetype)init {
self = [super init];
if (self) {
// __weak typeof(self) weakSelf = self;
self.currentThread = [[NSThread alloc] initWithBlock:^{
// 创建上下文
CFRunLoopSourceContext context = {0};
// 创建source
CFRunLoopSourceRef source = CFRunLoopSourceCreate(kCFAllocatorDefault, 0, &context);
// 往RunLoop中添加source
CFRunLoopAddSource(CFRunLoopGetCurrent(), source, kCFRunLoopDefaultMode);
// 启动
CFRunLoopRunInMode(kCFRunLoopDefaultMode, 1.0e10, false);
// 销毁source
CFRelease(source);
// while (weakSelf && !weakSelf.isStopped) {
// // 启动,第三个参数,设置为true,代表执行完source后就会退出当前的loop
// CFRunLoopRunInMode(kCFRunLoopDefaultMode, 1.0e10, true);
// }
}];
// 线程启动
[self.currentThread start];
}
return self;
}
/// 在常驻线程中执行动作
/// @param task block中的内容是在常驻线程中执行的行为
- (void)executeTask:(void (^)(void))task {
if (!self.currentThread || !task) {
return;
}
// 去子线程执行方法
[self performSelector:@selector(threadExecuteTask:) onThread:self.currentThread withObject:task waitUntilDone:NO];
}
/// 停止常驻线程
- (void)stop {
if (!self.currentThread) return;
/* 去子线程停止RunLoop
* waitUntilDone=YES,表示当前方法执行完毕后再执行别的
*/
[self performSelector:@selector(stopThread) onThread:self.currentThread withObject:nil waitUntilDone:YES];
}
/// 在线程中执行内容
/// @param task 内容
- (void)threadExecuteTask:(void (^)(void))task {
task();
}
/// 停止线程
- (void)stopThread {
// // 标识设置成YES
// self.isStopped = YES;
// 停止当前线程对应的Runloop
CFRunLoopStop(CFRunLoopGetCurrent());
self.currentThread = nil;
}
@end
C语言版本使用:
#import "AViewController.h"
#import "PermanentCThread.h"
@interface AViewController ()
@property (nonatomic, strong) PermanentCThread *thread;
@end
@implementation AViewController
- (void)dealloc {
NSLog(@"%s",__func__);
}
- (void)viewDidLoad {
[super viewDidLoad];
self.thread = [[PermanentCThread alloc] init];
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
__weak typeof(self) weakSelf = self;
[self.thread executeTask:^{
[weakSelf printSomething];
}];
NSLog(@"点击了界面");
}
// 点击了停止按钮
- (IBAction)clickStop {
[self.thread stop];
}
- (void)printSomething {
// sleep(3);
NSLog(@"当前的线程是 -- %@",[NSThread currentThread]);
}
@end
点击了界面
当前的线程是 -- <NSThread: 0x6000025290c0>{number = 6, name = (null)}
点击了界面
当前的线程是 -- <NSThread: 0x6000025290c0>{number = 6, name = (null)}
点击了界面
当前的线程是 -- <NSThread: 0x6000025290c0>{number = 6, name = (null)}