Notification多线程 重定向

来源:互联网 发布:java面试笔试题及答案 编辑:程序博客网 时间:2024/06/14 13:27

如果我们的Notification是在二级线程中post的,如何能在主线程中对这个Notification进行处理呢?或者换个提法,如果我们希望一个Notification的post线程与转发线程不是同一个线程,应该怎么办呢?

“重定向”:

就是我们在Notification所在的默认线程中捕获这些分发的通知,然后将其重定向到指定的线程中。

一种重定向的实现思路是自定义一个通知队列(注意,不是NSNotificationQueue对象,而是一个数组),让这个队列去维护那些我们需要重定向的Notification。我们仍然是像平常一样去注册一个通知的观察者,当Notification来了时,先看看post这个Notification的线程是不是我们所期望的线程,如果不是,则将这个Notification存储到我们的队列中,并发送一个信号(signal)到期望的线程中,来告诉这个线程需要处理一个Notification。指定的线程在收到信号后,将Notification从队列中移除,并进行处理



@interface ViewController ()<NSMachPortDelegate>

@property (nonatomic)NSMutableArray    * notifications;        // 通知队列

@property (nonatomic)NSThread          * notificationThread;   // 期望线程

@property (nonatomic)NSLock            * notificationLock;     // 用于对通知队列加锁的锁对象,避免线程冲突

@property (nonatomic)NSMachPort        * notificationPort;     // 用于向期望线程发送信号的通信端口

@end


@implementation ViewController

- (void)viewDidLoad

{

    [superviewDidLoad];


    NSLog(@"current thread = %@", [NSThreadcurrentThread]);


    // 初始化

    self.notifications = [[NSMutableArrayalloc] init];

    self.notificationLock = [[NSLockalloc] init];


    self.notificationThread = [NSThreadcurrentThread];

    self.notificationPort = [[NSMachPortalloc] init];

    self.notificationPort.delegate =self;


    // 往当前线程的run loop添加端口源

    // Mach消息到达而接收线程的run loop没有运行时,则内核会保存这条消息,直到下一次进入run loop

    [[NSRunLoopcurrentRunLoop] addPort:self.notificationPort

                                forMode:(__bridgeNSString *)kCFRunLoopCommonModes];


    [[NSNotificationCenterdefaultCenter] addObserver:selfselector:@selector(processNotification:)name:@"TestNotification"object:nil];


    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{


        [[NSNotificationCenterdefaultCenter] postNotificationName:TEST_NOTIFICATIONobject:@""userInfo:nil];


    });

}


- (void)handleMachMessage:(void *)msg {


    [self.notificationLocklock];


    while ([self.notificationscount]) {

        NSNotification *notification = [self.notificationsobjectAtIndex:0];

        [self.notificationsremoveObjectAtIndex:0];

        [self.notificationLockunlock];

        [selfprocessNotification:notification];

        [self.notificationLocklock];

    };


    [self.notificationLockunlock];

}


- (void)processNotification:(NSNotification *)notification {


    if ([NSThreadcurrentThread] != _notificationThread) {

        // Forward the notification to the correct thread.

        [self.notificationLocklock];

        [self.notificationsaddObject:notification];

        [self.notificationLockunlock];

        [self.notificationPortsendBeforeDate:[NSDatedate]

                                   components:nil

                                         from:nil

                                     reserved:0];

    }

    else {

        // Process the notification here;

        NSLog(@"current thread = %@", [NSThreadcurrentThread]);

        NSLog(@"process notification");

    }

}

运行后,其输出如下:

1
2
3
2015-03-11 23:38:31.637 test[1474:92483] current thread = {number = 1, name = main}
2015-03-11 23:38:31.663 test[1474:92483] current thread = {number = 1, name = main}
2015-03-11 23:38:31.663 test[1474:92483] process notification

可以看到,我们在全局dispatch队列中抛出的Notification,如愿地在主线程中接收到了



0 0
原创粉丝点击