美文网首页
RunLoop -- 线程保活

RunLoop -- 线程保活

作者: 踩坑小分队 | 来源:发表于2020-04-11 21:23 被阅读0次

    使用场景:
    如果一个操作需要在子线程操作,串行,非并发。如果按照之前的逻辑,可能触发的时候就需要创建一个子线程,操作,然后线程销毁,下次操作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)}
    

    相关文章

      网友评论

          本文标题:RunLoop -- 线程保活

          本文链接:https://www.haomeiwen.com/subject/pepumhtx.html