2010-01-07 6 views
5

Ich benutze iPhone SDK 3.1.2, und der folgende Code zeigt die NSOperationQueue nicht den Thread für jede Aufgabe wiederverwenden.NSOperationQueue nicht Thread auf iPhone

Der Code hat keine Probleme auf 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]); 
} 

Die Ausgabe zeigt, dass es 100 Threads erstellt, um die 100 Aufgaben auszuführen.

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 
+0

Ich mag würde wissen, dass auch ... – gcamp

+0

Warum keine Rolle spielt, ob die Warteschlange op Wiederverwendung von Threads ist oder nicht? –

+0

@Peter Hosey - Ich schätze, es ist nicht die Wiederverwendung, sondern die maximale Threadanzahl, um die er sich Sorgen macht. Zu viele CPU-gebundene Threads führen zu einem Leistungsabfall. – DougW

Antwort

9

NSOperationQueue ist so konzipiert, bündeln und Weiterverwendung Threads auf die effizienteste Art und Weise möglich, und in diesem Fall scheint es nicht entschieden wieder mit Themen wurde der beste Weg zu gehen.

Testcode hat seinen Nutzen (und es ist möglich, dass Sie einen Eckfall identifiziert haben, wo NSOperationQueue nicht die effizienteste Sache macht), aber das bedeutet nicht, dass NSOperationQueue immer schrecklich ineffizient ist, wenn Sie mit echtem Code umgehen wahres Leben; In der Tat war meine eigene Erfahrung im Gegenteil.

Also ich würde sagen, verwenden Sie es in Ihrem echten Code und wenn Sie Leistungsprobleme haben, graben Sie weiter in das, was es mit Threads hinter den Kulissen tut. Ansonsten mach dir keine Sorgen darüber.

Nebenbei, wenn Sie noch neugierig sind, könnten Sie versuchen, die Namen der Threads in einem Array von NSStrings aufzuzeichnen und dann alles am Ende des Testcodes auszudrucken, anstatt sich zu protokollieren, während Sie weitermachen - dies wird den Arbeitsaufwand jeder NSInvocationOperation erheblich reduzieren.

2

Snow Leopards Implementierung von NSOperation/NSOperationQueue basiert nun auf GCD.

Das iPhone verwendet immer noch die alte Leopard-Implementierung. Sie können also auf jeder Plattform unterschiedliche Ergebnisse erwarten (ganz zu schweigen von der komplett anderen Hardware).

Es ist möglich, dass das Erstellen neuer Threads der effizienteste Weg ist, um die Aufgaben zu erledigen, die Sie NSOperationQueue geben.

0

NSOperationQueue führt seine hinzugefügten Vorgänge asynchron (in einem separaten Thread) aus. Wenn wir also Thread-Informationen drucken, ist es möglich, dass wir das gleiche Thread-Objekt die meiste Zeit bekommen.

NSOperation-Objekt, das in NSOperationQueue hinzugefügt wurde, ist unterschiedlich, Thread-Objekte können jedoch identisch sein.

- (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]); 
} 
Verwandte Themen