NSOperationQueue在iPhone上不会重用线程

5
我正在使用iPhone SDK 3.1.2,以下代码显示NSOperationQueue不会为每个任务重用线程。
在Snow Leopard上,此代码没有任何问题。
- (void)applicationDidFinishLaunching:(UIApplication *)application {    

    // Override point for customization after app launch    
    [window addSubview:viewController.view];
    [window makeKeyAndVisible];

    NSOperationQueue *queue = [[NSOperationQueue alloc] init];
    [queue setMaxConcurrentOperationCount:1];
    for(int i = 0; i < 100; i++) {
        NSInvocationOperation *op = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(run) object:nil];
        [queue addOperation:op];
        [op release];
    }
}

- (void)run {
    static int tc = 0;
    if([[NSThread currentThread] isMainThread]) {
        NSLog(@"MAIN THREAD");
        return;
    } else if([[NSThread currentThread] name] == nil) {
        [[NSThread currentThread] setName:[NSString stringWithFormat:@"THREAD_%d", tc++]];
    }
    NSLog(@"%@", [[NSThread currentThread] name]);
}

输出结果显示它创建了100个线程来执行100个任务。
2010-01-07 11:46:03.502 OperationQueueTest[7911:4503] THREAD_0
2010-01-07 11:46:03.506 OperationQueueTest[7911:4d03] THREAD_1
2010-01-07 11:46:03.507 OperationQueueTest[7911:4807] THREAD_2
2010-01-07 11:46:03.510 OperationQueueTest[7911:4d07] THREAD_3
2010-01-07 11:46:03.514 OperationQueueTest[7911:5007] THREAD_4
2010-01-07 11:46:03.516 OperationQueueTest[7911:4f0b] THREAD_5
2010-01-07 11:46:03.518 OperationQueueTest[7911:4e0f] THREAD_6
...
2010-01-07 11:46:03.740 OperationQueueTest[7911:4ea7] THREAD_97
2010-01-07 11:46:03.744 OperationQueueTest[7911:4dcf] THREAD_98
2010-01-07 11:46:03.746 OperationQueueTest[7911:460f] THREAD_99

我也想知道... - gcamp
为什么操作队列是否重用线程很重要? - Peter Hosey
@Peter Hosey - 我猜他担心的不是重新使用,而是最大线程数。太多CPU绑定的线程会影响性能。 - DougW
3个回答

9
NSOperationQueue旨在以最高效的方式池化和重用线程,在这种情况下,它似乎决定不重用线程是最好的方法。
测试代码有其用途(可能您已经发现了一个NSOperationQueue无法处理最有效事务的特殊情况),但这并不意味着NSOperationQueue在处理实际代码时总是非常低效;事实上,我的经验恰恰相反。
因此,我建议您在实际代码中使用它,如果遇到性能问题,请进一步了解其在幕后如何处理线程。否则就不必担心它。
顺便说一句,如果您仍然感到好奇,可以尝试将线程名称记录到NSString数组中,然后在测试代码结束时打印所有内容,而不是在进行日志记录时 - 这将大大减少每个NSInvocationOperation所做的工作量。

2

雪豹系统中的NSOperation/NSOperationQueue实现现在基于GCD。

iPhone仍然使用旧的Leopard实现。因此,您可以在每个平台上期望不同的结果(更不用说完全不同的硬件了)。

可能产生新线程是完成给定任务的NSOperationQueue最有效的方式。


0

NSOperationQueue执行其添加的操作是异步的(在单独的线程中)。因此,如果我们打印线程信息,很可能大部分时间都会得到相同的线程对象。

添加到NSOperationQueue中的NSOperation对象可能不同,但线程对象可能相同。

- (void)operaitonqueueTest
{

    _opQueue = [[NSOperationQueue alloc] init];
    [_opQueue setMaxConcurrentOperationCount:5];
    for(int i = 0; i < 50; i++) {
        NSInvocationOperation *op = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(run) object:nil];
        [_opQueue addOperation:op];
    }
}

- (void)run {
    if([[NSThread currentThread] isMainThread]) {
        NSLog(@"MAIN THREAD");
        return;
    }
    NSLog(@"currentThread = %@", [NSThread currentThread]);
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接