2015-04-23 50 views
0

我想同時獲得三個請求以提高性能。 這裏我當前的代碼,它在我的tableview只返回一個平臺:如何在同一時間用三個請求正確創建併發隊列

dispatch_queue_t concurrentQueue = dispatch_queue_create("com.myapp.myqueue", DISPATCH_QUEUE_CONCURRENT); 

void(^block_readPS4)() = ^{ 
    self.releasesDict = [NSDictionary dictionaryWithDictionary:[self getDataWithPlatform:@"ps4"]]; 
}; 
void(^block_readXONE)() = ^{ 
    self.releasesDict = [NSDictionary dictionaryWithDictionary:[self getDataWithPlatform:@"xboxone"]]; 
}; 
void(^block_readPC)() = ^{ 
    self.releasesDict = [NSDictionary dictionaryWithDictionary:[self getDataWithPlatform:@"pc"]]; 
}; 
void(^block_write)() = ^{dictionaryWithDictionary:self.releasesDict]; 
    self.releasesArr = [self.releasesDict allKeys]; 
    [self.tableView reloadData]; 
    [self.activityInd stopAnimating]; 
}; 
dispatch_async(concurrentQueue,block_readPS4); 
dispatch_async(concurrentQueue,block_readXONE); 
dispatch_async(concurrentQueue,block_readPC); 

dispatch_barrier_async(concurrentQueue, block_write); 

我知道問題在self.releasesDict寫,怎麼還可以提高?

回答

1

您在每次讀取時都覆蓋self.releasesDict。因此,在您的寫入塊中,self.releasesDict的值將是系統執行的最後一次讀取。如果你希望所有閱讀相同的NSDictionary聲明self.releasesDictNSMutableDictionary,並初始化它:

self.releasesDict = [NSMutableDictionary dictionary]; 

,並在您閱讀:

[self.releasesDict addEntriesFromDictionary:[NSDictionary dictionaryWithDictionary:/*what you want*/]]; 
+0

謝謝UA很多,現在工作 – pluck

+0

這不是安全地調用'addEntriesFromDictionary:'從(可能)多個併發線程。 – ipmcc

4

@ryancrunchi是正確的:

你」在每次閱讀中重寫self.releasesDict。因此,在您編寫 塊時,self.releasesDict的值將是系統執行的最後一次讀取。

...但他提出的解決方案不能保護字典免受併發寫入,並且NSMutableDictionary本質上不是線程安全的。您必須保護它免受併發讀取+寫入和/或寫入+寫入。這裏是你可以做的一個方法(一切的詳細解說的評論正在做):

// A local (non-shared) mutable dictionary. Using a local dictionary allows us to know that no one 
// else is reading from or writing to it concurrently, which is not guaranteed if we use self.releasesDict 
NSMutableDictionary* localDict = [NSMutableDictionary dictionary]; 

// Your original concurrent queue 
dispatch_queue_t concurrentQueue = dispatch_queue_create("com.myapp.myqueue", DISPATCH_QUEUE_CONCURRENT); 

// A serial queue to protect localDict from reading and writing. 
dispatch_queue_t localDictWriteQueue = dispatch_queue_create(NULL, DISPATCH_QUEUE_SERIAL); 

// Make this queue target the concurrent queue. Not strictly required, but you had everything executing on 
// concurrentQueue before, and this preserves that, while also protecting localDict. 
dispatch_set_target_queue(localDictWriteQueue, concurrentQueue); 

// A dispatch group that allows us to perform an operation only after all the constituent writes have finished. 
dispatch_group_t group = dispatch_group_create(); 

// For each platform, enter the group, then fire off the concurrent block 
dispatch_group_enter(group); 
dispatch_async(concurrentQueue, ^{ 
    // Fetch into a dictionary that is local to the block. 
    NSDictionary* x = [self getDataWithPlatform:@"ps4"]; 

    // Then, on the serial localDictWriteQueue merge those entries into the shared local dictionary 
    dispatch_async(localDictWriteQueue, ^{ 
     [localDict addEntriesFromDictionary: x]; 
     // This balances out the dispatch_group_enter operation we did right before we enqueued this 
     dispatch_group_leave(group); 
    }); 
}); 

// Second verse, same as the first 
dispatch_group_enter(group); 
dispatch_async(concurrentQueue, ^{ 
    NSDictionary* x = [self getDataWithPlatform:@"xboxone"]; 
    dispatch_async(localDictWriteQueue, ^{ 
     [localDict addEntriesFromDictionary: x]; 
     dispatch_group_leave(group); 
    }); 
}); 

// Third verse, same as the first 
dispatch_group_enter(group); 
dispatch_async(concurrentQueue, ^{ 
    NSDictionary* x = [self getDataWithPlatform:@"pc"]; 
    dispatch_async(localDictWriteQueue, ^{ 
     [localDict addEntriesFromDictionary: x]; 
     dispatch_group_leave(group); 
    }); 
}); 

// Then set up the block we want to run at the end... use main queue because it updates UI. 
dispatch_group_notify(group, dispatch_get_main_queue(), ^{ 
    // Update self.releasesDict all at once, on the main thread 
    // Note: we do not need to do this read of localDict on localDictWriteQueue because if this block is executing, we know (semantically) that all possible 
    // write operations have already completed, and that no other writes to localDict are possible because it's local to this method call. 
    self.releasesDict = localDict; 
    // Same idea 
    self.releasesArr = [self.releasesDict allKeys]; 

    // Update UI based on state changes to self. 
    [self.tableView reloadData]; 
    [self.activityInd stopAnimating]; 
}); 
+0

謝謝你的解釋 – pluck

相關問題