多线程与通知

总结:

1、同一线程,添加多个观察者或者发送多次通知,就会响应多次方法

2、不管创建在哪个线程,发送在哪个线程接收就在哪个线程

3、接收在哪个线程可以由添加方法发来控制

4、接收在哪个线程可以由添加runloop端口的方法来控制

#import "ViewController.h"
#define TEST_NOTIFICATION @"TestNotification"
@interface ViewController ()<NSMachPortDelegate>
@property (nonatomic) NSMutableArray    *notifications;         // 通知队列
@property (nonatomic) NSThread          *notificationThread;    // 期望线程
@property (nonatomic) NSLock            *notificationLock;      // 用于对通知队列加锁的锁对象,避免线程冲突
@property (nonatomic) NSMachPort        *notificationPort;      // 用于向期望线程发送信号的通信端口
@end

@implementation ViewController
- (void)viewDidLoad {
    [super viewDidLoad];
    //    [self test5];
    //    [self test4];
    //    [self test3];
    //    [self test2];
    //    [self test1];

}
#pragma mark -添加一个观察者,发送两次响应两次
-(void)test5{
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(firstNotification:) name:TEST_NOTIFICATION object:nil];
    [[NSNotificationCenter defaultCenter] postNotificationName:TEST_NOTIFICATION object:nil userInfo:nil];
    [[NSNotificationCenter defaultCenter] postNotificationName:TEST_NOTIFICATION object:nil userInfo:nil];
}
#pragma mark - 添加多个观察者,发送一次响应两次
-(void)test4{
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(firstNotification:) name:TEST_NOTIFICATION object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(firstNotification:) name:TEST_NOTIFICATION object:nil];

    [[NSNotificationCenter defaultCenter] postNotificationName:TEST_NOTIFICATION object:nil userInfo:nil];
}
#pragma mark - 发送在子线程,接收在主线程(可以指定某一个线程,不一定非要主线程)
-(void)test3{
    [[NSNotificationCenter defaultCenter] addObserverForName:TEST_NOTIFICATION object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification * _Nonnull note) {
            NSLog(@"接收和处理通知的线程%@", [NSThread currentThread]);
        }];
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        [[NSNotificationCenter defaultCenter] postNotificationName:TEST_NOTIFICATION object:nil userInfo:nil];
        NSLog(@"发送通知的线程为%@", [NSThread currentThread]);
    });
}
#pragma mark - 发送在子线程,接收在主线程(接收在添加port所在loop的线程)

-(void)test2{
    NSLog(@"当前线程 = %@", [NSThread currentThread]);
    
    // 初始化
    self.notifications = [[NSMutableArray alloc] init];
    self.notificationLock = [[NSLock alloc] init];
    
    self.notificationThread = [NSThread currentThread];
    self.notificationPort = [[NSMachPort alloc] init];
    self.notificationPort.delegate = self;
    
    // 往当前线程的run loop添加端口源
    // 当Mach消息到达而接收线程的run loop没有运行时,则内核会保存这条消息,直到下一次进入run loop
    [[NSRunLoop currentRunLoop] addPort:self.notificationPort
                                forMode:(__bridge NSString *)kCFRunLoopCommonModes];
    
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(secondNotification:) name:TEST_NOTIFICATION object:nil];
    
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        NSLog(@"发送线程 = %@", [NSThread currentThread]);
        [[NSNotificationCenter defaultCenter] postNotificationName:TEST_NOTIFICATION object:nil userInfo:nil];
    
    });
}
//notificationPort代理方法
- (void)handleMachMessage:(void *)msg {
    NSLog(@"%s",__func__);

    [self.notificationLock lock];
    
    while ([self.notifications count]) {
        NSNotification *notification = [self.notifications objectAtIndex:0];
        [self.notifications removeObjectAtIndex:0];
        [self.notificationLock unlock];
        [self secondNotification:notification];
        [self.notificationLock lock];
    };
    
    [self.notificationLock unlock];
}
    
- (void)secondNotification:(NSNotification *)notification {
    NSLog(@"%s",__func__);
    if ([NSThread currentThread] != _notificationThread) {
        // Forward the notification to the correct thread.
        [self.notificationLock lock];
        [self.notifications addObject:notification];
        [self.notificationLock unlock];
        [self.notificationPort sendBeforeDate:[NSDate date]
                                   components:nil
                                         from:nil
                                     reserved:0];

    }
    else {
        // Process the notification here;
        NSLog(@"接收线程 = %@", [NSThread currentThread]);
        NSLog(@"通知流程结束");
    }
}
#pragma mark - 创建在同一个线程,发送和接收在一个线程

-(void)test1{
        NSLog(@"当前线程为%@", [NSThread currentThread]);//0
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(firstNotification:) name:TEST_NOTIFICATION object:nil];

        dispatch_async(dispatch_get_global_queue(0, 0), ^{
            [[NSNotificationCenter defaultCenter] postNotificationName:TEST_NOTIFICATION object:nil userInfo:nil];
            NSLog(@"发送通知的线程为%@", [NSThread currentThread]);//1
        });
}

- (void)firstNotification:(NSNotification *)notification {
    NSLog(@"接收线程%@", [NSThread currentThread]);//1
}
@end

猜你喜欢

转载自blog.csdn.net/u011374880/article/details/124947540