🎯 Recommended Samples
Balanced sample collections from various categories for you to explore
macOS Multithreading Objective-C Samples
macOS Objective-C multithreading examples including NSThread, NSOperationQueue, Grand Central Dispatch, and synchronization primitives
💻 NSThread Basics objectivec
🟢 simple
⭐⭐⭐
Create and manage threads using NSThread with detach, init, and synchronization
⏱️ 25 min
🏷️ objectivec, macos, multithreading, nsthread
Prerequisites:
Objective-C basics, Foundation framework
// macOS Objective-C NSThread Basics
// Using Foundation framework
#import <Foundation/Foundation.h>
// MARK: - 1. Creating Threads with NSThread
@interface ThreadWorker : NSObject
// Worker method that runs on separate thread
- (void)doWork {
@autoreleasepool {
NSLog(@"[Thread] Work started on thread: %@", [NSThread currentThread]);
for (int i = 0; i < 5; i++) {
NSLog(@"[Thread] Working... %d", i + 1);
[NSThread sleepForTimeInterval:0.5];
}
NSLog(@"[Thread] Work completed");
}
}
// Worker method with parameters
- (void)doWorkWithObject:(id)object {
@autoreleasepool {
NSString *taskName = (NSString *)object;
NSLog(@"[Thread] Task '%@' started on thread: %@", taskName, [NSThread currentThread]);
for (int i = 0; i < 3; i++) {
NSLog(@"[Thread] %@ - Step %d", taskName, i + 1);
[NSThread sleepForTimeInterval:0.3];
}
NSLog(@"[Thread] Task '%@' completed", taskName);
}
}
@end
// MARK: - 2. Thread with Custom Properties
@interface CustomThread : NSThread
@property (nonatomic, strong) NSString *taskName;
@property (nonatomic, assign) NSInteger iterations;
- (instancetype)initWithTaskName:(NSString *)name iterations:(NSInteger)iterations;
@end
@implementation CustomThread
- (instancetype)initWithTaskName:(NSString *)name iterations:(NSInteger)iterations {
self = [super init];
if (self) {
_taskName = name;
_iterations = iterations;
}
return self;
}
- (void)main {
@autoreleasepool {
NSLog(@"[CustomThread] %@ started", self.taskName);
for (NSInteger i = 0; i < self.iterations && !self.isCancelled; i++) {
NSLog(@"[CustomThread] %@ - Iteration %ld", self.taskName, (long)(i + 1));
[NSThread sleepForTimeInterval:0.2];
}
if (self.isCancelled) {
NSLog(@"[CustomThread] %@ was cancelled", self.taskName);
} else {
NSLog(@"[CustomThread] %@ completed", self.taskName);
}
}
}
@end
// MARK: - 3. Thread Synchronization
@interface SynchronizedWorker : NSObject
@property (nonatomic, strong) NSMutableArray *sharedArray;
@property (nonatomic, strong) NSLock *arrayLock;
- (instancetype)init;
- (void)addToArray:(NSString *)value;
- (void)printArray;
@end
@implementation SynchronizedWorker
- (instancetype)init {
self = [super init];
if (self) {
_sharedArray = [NSMutableArray array];
_arrayLock = [[NSLock alloc] init];
}
return self;
}
- (void)addToArray:(NSString *)value {
[self.arrayLock lock];
@try {
[self.sharedArray addObject:value];
NSLog(@"Added: %@", value);
} @finally {
[self.arrayLock unlock];
}
}
- (void)printArray {
[self.arrayLock lock];
@try {
NSLog(@"Array contents: %@", self.sharedArray);
} @finally {
[self.arrayLock unlock];
}
}
@end
// MARK: - 4. Thread Communication
@interface ProducerConsumer : NSObject
@property (nonatomic, strong) NSMutableArray *buffer;
@property (nonatomic, strong) NSCondition *condition;
@property (nonatomic, assign) NSInteger bufferSize;
- (instancetype)initWithBufferSize:(NSInteger)size;
- (void)produce:(NSString *)item;
- (NSString *)consume;
@end
@implementation ProducerConsumer
- (instancetype)initWithBufferSize:(NSInteger)size {
self = [super init];
if (self) {
_buffer = [NSMutableArray array];
_condition = [[NSCondition alloc] init];
_bufferSize = size;
}
return self;
}
- (void)produce:(NSString *)item {
[self.condition lock];
while ([self.buffer count] >= self.bufferSize) {
NSLog(@"Buffer full, producer waiting...");
[self.condition wait];
}
[self.buffer addObject:item];
NSLog(@"Produced: %@ (buffer size: %lu)", item, (unsigned long)[self.buffer count]);
[self.condition signal];
[self.condition unlock];
}
- (NSString *)consume {
[self.condition lock];
while ([self.buffer count] == 0) {
NSLog(@"Buffer empty, consumer waiting...");
[self.condition wait];
}
NSString *item = [self.buffer firstObject];
[self.buffer removeObjectAtIndex:0];
NSLog(@"Consumed: %@ (buffer size: %lu)", item, (unsigned long)[self.buffer count]);
[self.condition signal];
[self.condition unlock];
return item;
}
@end
// MARK: - Main Demonstration
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSLog(@"=== macOS Objective-C NSThread Examples ===\n");
// 1. Detached thread
NSLog(@"--- 1. Detached New Thread ---");
ThreadWorker *worker1 = [[ThreadWorker alloc] init];
[NSThread detachNewThreadSelector:@selector(doWork)
toTarget:worker1
withObject:nil];
[NSThread sleepForTimeInterval:3.0];
// 2. Thread with object parameter
NSLog(@"\n--- 2. Thread with Object Parameter ---");
ThreadWorker *worker2 = [[ThreadWorker alloc] init];
[NSThread detachNewThreadSelector:@selector(doWorkWithObject:)
toTarget:worker2
withObject:@"Task A"];
[NSThread detachNewThreadSelector:@selector(doWorkWithObject:)
toTarget:worker2
withObject:@"Task B"];
[NSThread sleepForTimeInterval:2.0];
// 3. Custom thread instance
NSLog(@"\n--- 3. Custom Thread Instance ---");
CustomThread *thread1 = [[CustomThread alloc] initWithTaskName:@"Custom Task 1" iterations:5];
CustomThread *thread2 = [[CustomThread alloc] initWithTaskName:@"Custom Task 2" iterations:3];
[thread1 start];
[thread2 start];
// Wait for threads to complete
while (thread1.isExecuting || thread2.isExecuting) {
[NSThread sleepForTimeInterval:0.1];
}
// 4. Thread cancellation
NSLog(@"\n--- 4. Thread Cancellation ---");
CustomThread *longThread = [[CustomThread alloc] initWithTaskName:@"Long Task" iterations:100];
[longThread start];
[NSThread sleepForTimeInterval:0.5];
NSLog(@"Cancelling long task...");
[longThread cancel];
// Wait for cancellation
while (longThread.isExecuting) {
[NSThread sleepForTimeInterval:0.1];
}
// 5. Synchronized access
NSLog(@"\n--- 5. Synchronized Access ---");
SynchronizedWorker *syncWorker = [[SynchronizedWorker alloc] init];
for (int i = 0; i < 5; i++) {
NSString *value = [NSString stringWithFormat:@"Item-%d", i];
[NSThread detachNewThreadSelector:@selector(addToArray:)
toTarget:syncWorker
withObject:value];
}
[NSThread sleepForTimeInterval:1.0];
[syncWorker printArray];
// 6. Producer-consumer pattern
NSLog(@"\n--- 6. Producer-Consumer Pattern ---");
ProducerConsumer *pc = [[ProducerConsumer alloc] initWithBufferSize:3];
// Producer thread
[NSThread detachNewThreadSelector:@selector(producerThread) toTarget:pc withObject:nil];
// Consumer thread
[NSThread detachNewThreadSelector:@selector(consumerThread) toTarget:pc withObject:nil];
[NSThread sleepForTimeInterval:2.0];
NSLog(@"\n=== NSThread Examples Completed ===");
}
return 0;
}
// Producer thread method
@implementation ProducerConsumer (ProducerThread)
- (void)producerThread {
@autoreleasepool {
for (int i = 0; i < 5; i++) {
NSString *item = [NSString stringWithFormat:@"Product-%d", i];
[self produce:item];
[NSThread sleepForTimeInterval:0.2];
}
}
}
@end
// Consumer thread method
@implementation ProducerConsumer (ConsumerThread)
- (void)consumerThread {
@autoreleasepool {
for (int i = 0; i < 5; i++) {
[self consume];
[NSThread sleepForTimeInterval:0.3];
}
}
}
@end
💻 NSOperationQueue objectivec
🟡 intermediate
⭐⭐⭐⭐
Manage concurrent operations with NSOperationQueue, dependencies, priority levels, and completion blocks
⏱️ 35 min
🏷️ objectivec, macos, multithreading, nsoperation
Prerequisites:
Intermediate Objective-C, Foundation framework
// macOS Objective-C NSOperationQueue Examples
// Using Foundation framework
#import <Foundation/Foundation.h>
// MARK: - 1. Basic NSBlockOperation
@interface BlockOperationDemo : NSObject
+ (void)demonstrateBlockOperations;
@end
@implementation BlockOperationDemo
+ (void)demonstrateBlockOperations {
NSLog(@"--- Block Operations ---");
// Create operation queue
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
queue.maxConcurrentOperationCount = 2;
// Create block operations
NSBlockOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"Operation 1 started");
[NSThread sleepForTimeInterval:1.0];
NSLog(@"Operation 1 completed");
}];
NSBlockOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"Operation 2 started");
[NSThread sleepForTimeInterval:0.5];
NSLog(@"Operation 2 completed");
}];
NSBlockOperation *op3 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"Operation 3 started");
[NSThread sleepForTimeInterval:0.3];
NSLog(@"Operation 3 completed");
}];
// Add completion blocks
[op3 setCompletionBlock:^{
NSLog(@"Operation 3 completion block executed");
}];
// Add operations to queue
[queue addOperations:@[op1, op2, op3] waitUntilFinished:YES];
NSLog(@"All block operations completed");
}
@end
// MARK: - 2. Custom NSOperation
@interface ImageProcessingOperation : NSOperation
@property (nonatomic, strong) NSString *imageName;
@property (nonatomic, strong) NSString *result;
- (instancetype)initWithImageName:(NSString *)name;
@end
@implementation ImageProcessingOperation {
BOOL _isExecuting;
BOOL _isFinished;
}
- (instancetype)initWithImageName:(NSString *)name {
self = [super init];
if (self) {
_imageName = name;
_isExecuting = NO;
_isFinished = NO;
}
return self;
}
- (BOOL)isAsynchronous {
return YES;
}
- (BOOL)isExecuting {
return _isExecuting;
}
- (BOOL)isFinished {
return _isFinished;
}
- (void)start {
if (self.isCancelled) {
[self willChangeValueForKey:@"isFinished"];
_isFinished = YES;
[self didChangeValueForKey:@"isFinished"];
return;
}
[self willChangeValueForKey:@"isExecuting"];
_isExecuting = YES;
[self didChangeValueForKey:@"isExecuting"];
// Perform operation on background thread
[self performOperation];
}
- (void)performOperation {
@autoreleasepool {
NSLog(@"Processing image: %@", self.imageName);
// Simulate image processing
[NSThread sleepForTimeInterval:0.5];
self.result = [NSString stringWithFormat:@"Processed_%@", self.imageName];
NSLog(@"Image processed: %@", self.result);
[self completeOperation];
}
}
- (void)completeOperation {
[self willChangeValueForKey:@"isExecuting"];
[self willChangeValueForKey:@"isFinished"];
_isExecuting = NO;
_isFinished = YES;
[self didChangeValueForKey:@"isExecuting"];
[self didChangeValueForKey:@"isFinished"];
}
- (void)cancel {
[super cancel];
NSLog(@"Cancelling operation for: %@", self.imageName);
}
@end
// MARK: - 3. Operation Dependencies
@interface DependencyDemo : NSObject
+ (void)demonstrateDependencies;
@end
@implementation DependencyDemo
+ (void)demonstrateDependencies {
NSLog(@"\n--- Operation Dependencies ---");
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
queue.maxConcurrentOperationCount = 3;
// Create operations
NSBlockOperation *downloadOp = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"Downloading data...");
[NSThread sleepForTimeInterval:1.0];
NSLog(@"Download complete");
}];
NSBlockOperation *parseOp = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"Parsing data...");
[NSThread sleepForTimeInterval:0.5];
NSLog(@"Parsing complete");
}];
NSBlockOperation *saveOp = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"Saving data...");
[NSThread sleepForTimeInterval:0.3];
NSLog(@"Save complete");
}];
NSBlockOperation *notifyOp = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"Sending notification...");
[NSThread sleepForTimeInterval:0.2];
NSLog(@"Notification sent");
}];
// Set dependencies
// parse depends on download
[parseOp addDependency:downloadOp];
// save depends on parse
[saveOp addDependency:parseOp];
// notify depends on save
[notifyOp addDependency:saveOp];
NSLog(@"Dependency chain: download -> parse -> save -> notify");
// Add to queue
[queue addOperations:@[notifyOp, saveOp, parseOp, downloadOp] waitUntilFinished:YES];
NSLog(@"All operations completed in correct order");
}
@end
// MARK: - 4. Operation Priority
@interface PriorityDemo : NSObject
+ (void)demonstratePriority;
@end
@implementation PriorityDemo
+ (void)demonstratePriority {
NSLog(@"\n--- Operation Priority ---");
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
queue.maxConcurrentOperationCount = 1;
// Create operations with different priorities
NSBlockOperation *lowOp = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"Low priority operation executing");
[NSThread sleepForTimeInterval:0.5];
}];
lowOp.queuePriority = NSOperationQueuePriorityLow;
NSBlockOperation *normalOp = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"Normal priority operation executing");
[NSThread sleepForTimeInterval:0.5];
}];
normalOp.queuePriority = NSOperationQueuePriorityNormal;
NSBlockOperation *highOp = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"High priority operation executing");
[NSThread sleepForTimeInterval:0.5];
}];
highOp.queuePriority = NSOperationQueuePriorityHigh;
// Add in random order
[queue addOperation:normalOp];
[queue addOperation:lowOp];
[queue addOperation:highOp];
[queue waitUntilAllOperationsAreFinished];
NSLog(@"Priority demo completed");
}
@end
// MARK: - 5. Concurrent Operations with Semaphores
@interface ConcurrentDemo : NSObject
+ (void)demonstrateConcurrent;
@end
@implementation ConcurrentDemo
+ (void)demonstrateConcurrent {
NSLog(@"\n--- Concurrent Operations with Limit ---");
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
queue.maxConcurrentOperationCount = 3;
NSLog(@"Starting 10 operations with max concurrent = 3");
for (NSInteger i = 0; i < 10; i++) {
NSInteger index = i;
NSBlockOperation *op = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"Operation %ld started", (long)index);
[NSThread sleepForTimeInterval:0.5];
NSLog(@"Operation %ld completed", (long)index);
}];
[queue addOperation:op];
}
[queue waitUntilAllOperationsAreFinished];
NSLog(@"All concurrent operations completed");
}
@end
// MARK: - 6. Operation with Progress
@interface ProgressOperation : NSOperation
@property (nonatomic, assign) NSInteger totalSteps;
@property (nonatomic, copy) void (^progressHandler)(double progress);
- (instancetype)initWithTotalSteps:(NSInteger)steps
progressHandler:(void (^)(double))progressHandler;
@end
@implementation ProgressOperation {
BOOL _isExecuting;
BOOL _isFinished;
}
- (instancetype)initWithTotalSteps:(NSInteger)steps
progressHandler:(void (^)(double))progressHandler {
self = [super init];
if (self) {
_totalSteps = steps;
_progressHandler = progressHandler;
_isExecuting = NO;
_isFinished = NO;
}
return self;
}
- (BOOL)isAsynchronous {
return YES;
}
- (BOOL)isExecuting {
return _isExecuting;
}
- (BOOL)isFinished {
return _isFinished;
}
- (void)start {
[self willChangeValueForKey:@"isExecuting"];
_isExecuting = YES;
[self didChangeValueForKey:@"isExecuting"];
[self performOperation];
}
- (void)performOperation {
for (NSInteger i = 0; i < self.totalSteps && !self.isCancelled; i++) {
[NSThread sleepForTimeInterval:0.2];
double progress = (double)(i + 1) / (double)self.totalSteps;
if (self.progressHandler) {
self.progressHandler(progress);
}
NSLog(@"Progress: %.0f%%", progress * 100);
}
[self completeOperation];
}
- (void)completeOperation {
[self willChangeValueForKey:@"isExecuting"];
[self willChangeValueForKey:@"isFinished"];
_isExecuting = NO;
_isFinished = YES;
[self didChangeValueForKey:@"isExecuting"];
[self didChangeValueForKey:@"isFinished"];
}
@end
// MARK: - 7. Operation Queue Management
@interface QueueManager : NSObject
@property (nonatomic, strong) NSOperationQueue *queue;
@property (nonatomic, strong) NSMutableArray<NSOperation *> *activeOperations;
- (instancetype)init;
- (void)addOperation:(NSOperation *)operation;
- (void)cancelAllOperations;
- (void)suspend;
- (void)resume;
@end
@implementation QueueManager
- (instancetype)init {
self = [super init];
if (self) {
_queue = [[NSOperationQueue alloc] init];
_queue.maxConcurrentOperationCount = 4;
_queue.name = @"com.example.queue";
_activeOperations = [NSMutableArray array];
}
return self;
}
- (void)addOperation:(NSOperation *)operation {
[self.activeOperations addObject:operation];
__weak typeof(self) weakSelf = self;
[operation setCompletionBlock:^{
__strong typeof(weakSelf) strongSelf = weakSelf;
if (strongSelf) {
[strongSelf.activeOperations removeObject:operation];
NSLog(@"Active operations: %lu", (unsigned long)strongSelf.activeOperations.count);
}
}];
[self.queue addOperation:operation];
}
- (void)cancelAllOperations {
NSLog(@"Cancelling %lu operations", (unsigned long)self.activeOperations.count);
for (NSOperation *op in self.activeOperations) {
[op cancel];
}
[self.activeOperations removeAllObjects];
}
- (void)suspend {
[self.queue setSuspended:YES];
NSLog(@"Queue suspended");
}
- (void)resume {
[self.queue setSuspended:NO];
NSLog(@"Queue resumed");
}
@end
// MARK: - Main Demonstration
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSLog(@"=== macOS Objective-C NSOperationQueue Examples ===\n");
// 1. Block operations
[BlockOperationDemo demonstrateBlockOperations];
// 2. Custom operation
NSLog(@"\n--- Custom Operations ---");
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
queue.maxConcurrentOperationCount = 2;
NSMutableArray *results = [NSMutableArray array];
for (NSInteger i = 0; i < 5; i++) {
ImageProcessingOperation *op = [[ImageProcessingOperation alloc]
initWithImageName:[NSString stringWithFormat:@"Image%ld", (long)i]];
[op setCompletionBlock:^{
if (op.result) {
@synchronized(results) {
[results addObject:op.result];
}
}
}];
[queue addOperation:op];
}
[queue waitUntilAllOperationsAreFinished];
NSLog(@"Processed images: %@", results);
// 3. Dependencies
[DependencyDemo demonstrateDependencies];
// 4. Priority
[PriorityDemo demonstratePriority];
// 5. Concurrent operations
[ConcurrentDemo demonstrateConcurrent];
// 6. Progress tracking
NSLog(@"\n--- Progress Tracking ---");
ProgressOperation *progressOp = [[ProgressOperation alloc]
initWithTotalSteps:5
progressHandler:^(double progress) {
NSLog(@"Progress callback: %.0f%%", progress * 100);
}];
[progressOp start];
while (progressOp.isExecuting) {
[NSThread sleepForTimeInterval:0.1];
}
// 7. Queue management
NSLog(@"\n--- Queue Management ---");
QueueManager *manager = [[QueueManager alloc] init];
for (NSInteger i = 0; i < 5; i++) {
NSBlockOperation *op = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"Managed operation %ld executing", (long)i);
[NSThread sleepForTimeInterval:0.5];
}];
[manager addOperation:op];
}
[NSThread sleepForTimeInterval:0.3];
[manager suspend];
[NSThread sleepForTimeInterval:0.5];
[manager resume];
[manager.queue waitUntilAllOperationsAreFinished];
NSLog(@"\n=== NSOperationQueue Examples Completed ===");
}
return 0;
}
💻 Grand Central Dispatch (GCD) objectivec
🟡 intermediate
⭐⭐⭐⭐
Use GCD for async operations, dispatch queues, semaphores, groups, and barriers
⏱️ 40 min
🏷️ objectivec, macos, multithreading, gcd
Prerequisites:
Intermediate Objective-C, Dispatch framework
// macOS Objective-C Grand Central Dispatch Examples
// Using Foundation and Dispatch framework
#import <Foundation/Foundation.h>
// MARK: - 1. Dispatch Queues
@interface GCDBasics : NSObject
+ (void)demonstrateDispatchQueues;
@end
@implementation GCDBasics
+ (void)demonstrateDispatchQueues {
NSLog(@"--- Dispatch Queues ---");
// Main queue
NSLog(@"Is main thread: %@", [NSThread isMainThread] ? @"YES" : @"NO");
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"Main queue: Is main thread: %@", [NSThread isMainThread] ? @"YES" : @"NO");
});
// Global queue with different priorities
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
NSLog(@"HIGH priority queue");
});
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSLog(@"DEFAULT priority queue");
});
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{
NSLog(@"LOW priority queue");
});
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
NSLog(@"BACKGROUND priority queue");
});
// Custom queue
dispatch_queue_t customQueue = dispatch_queue_create("com.example.custom", DISPATCH_QUEUE_SERIAL);
dispatch_async(customQueue, ^{
NSLog(@"Custom serial queue - Task 1");
});
dispatch_async(customQueue, ^{
NSLog(@"Custom serial queue - Task 2");
});
[NSThread sleepForTimeInterval:1.0];
}
@end
// MARK: - 2. Dispatch Sync vs Async
@interface SyncAsyncDemo : NSObject
+ (void)demonstrateSyncAsync;
@end
@implementation SyncAsyncDemo
+ (void)demonstrateSyncAsync {
NSLog(@"\n--- Sync vs Async ---");
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
NSLog(@"Before async dispatch");
dispatch_async(queue, ^{
NSLog(@"Async task started");
[NSThread sleepForTimeInterval:1.0];
NSLog(@"Async task completed");
});
NSLog(@"After async dispatch (immediate)");
NSLog(@"\nBefore sync dispatch");
dispatch_sync(queue, ^{
NSLog(@"Sync task started");
[NSThread sleepForTimeInterval:0.5];
NSLog(@"Sync task completed");
});
NSLog(@"After sync dispatch (waited)");
}
@end
// MARK: - 3. Dispatch After
@interface DelayDemo : NSObject
+ (void)demonstrateDelay;
@end
@implementation DelayDemo
+ (void)demonstrateDelay {
NSLog(@"\n--- Dispatch After ---");
NSLog(@"Scheduling delayed task...");
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)),
dispatch_get_main_queue(), ^{
NSLog(@"Delayed task executed after 2 seconds");
});
NSLog(@"Task scheduled, continuing...");
[NSThread sleepForTimeInterval:2.5];
}
@end
// MARK: - 4. Dispatch Groups
@interface GroupDemo : NSObject
+ (void)demonstrateGroups;
@end
@implementation GroupDemo
+ (void)demonstrateGroups {
NSLog(@"\n--- Dispatch Groups ---");
dispatch_group_t group = dispatch_group_create();
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
// Enter group manually
dispatch_group_enter(group);
dispatch_async(queue, ^{
NSLog(@"Task 1 started");
[NSThread sleepForTimeInterval:1.0];
NSLog(@"Task 1 completed");
dispatch_group_leave(group);
});
// Add to group automatically
dispatch_group_async(group, queue, ^{
NSLog(@"Task 2 started");
[NSThread sleepForTimeInterval:0.8];
NSLog(@"Task 2 completed");
});
dispatch_group_async(group, queue, ^{
NSLog(@"Task 3 started");
[NSThread sleepForTimeInterval:0.5]);
NSLog(@"Task 3 completed");
});
// Wait for all tasks
NSLog(@"Waiting for group...");
dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
NSLog(@"All group tasks completed");
// Notify when complete
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
NSLog(@"Group notify callback: All tasks done!");
});
[NSThread sleepForTimeInterval:0.5];
}
@end
// MARK: - 5. Dispatch Semaphores
@interface SemaphoreDemo : NSObject
+ (void)demonstrateSemaphores;
@end
@implementation SemaphoreDemo
+ (void)demonstrateSemaphores {
NSLog(@"\n--- Dispatch Semaphores ---");
// Create semaphore with initial value
dispatch_semaphore_t semaphore = dispatch_semaphore_create(3);
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
NSLog(@"Starting 10 tasks with semaphore (limit 3)");
for (NSInteger i = 0; i < 10; i++) {
dispatch_async(queue, ^{
// Wait for semaphore
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
NSLog(@"Task %ld started", (long)i);
// Simulate work
[NSThread sleepForTimeInterval:0.5];
NSLog(@"Task %ld completed", (long)i);
// Signal semaphore
dispatch_semaphore_signal(semaphore);
});
}
[NSThread sleepForTimeInterval:3.0);
// Semaphore as mutex
NSLog(@"\nSemaphore as mutex:");
dispatch_semaphore_t mutex = dispatch_semaphore_create(1);
__block NSInteger counter = 0;
for (NSInteger i = 0; i < 5; i++) {
dispatch_async(queue, ^{
dispatch_semaphore_wait(mutex, DISPATCH_TIME_FOREVER);
NSInteger value = counter++;
NSLog(@"Thread %ld read counter: %ld", (long)i, (long)value);
dispatch_semaphore_signal(mutex);
});
}
[NSThread sleepForTimeInterval:1.0];
}
@end
// MARK: - 6. Dispatch Barriers
@interface BarrierDemo : NSObject
+ (void)demonstrateBarriers;
@end
@implementation BarrierDemo
+ (void)demonstrateBarriers {
NSLog(@"\n--- Dispatch Barriers ---");
// Create concurrent queue
dispatch_queue_t queue = dispatch_queue_create("com.example.concurrent",
DISPATCH_QUEUE_CONCURRENT);
NSMutableArray *dataArray = [NSMutableArray array];
// Read operations (concurrent)
for (NSInteger i = 0; i < 3; i++) {
dispatch_async(queue, ^{
NSLog(@"Read %lu: %@", (unsigned long)i, dataArray);
});
}
// Write operation (barrier - exclusive)
dispatch_barrier_async(queue, ^{
NSLog(@"Barrier: Writing data");
[dataArray addObject:@"Item 1"];
[dataArray addObject:@"Item 2"];
[NSThread sleepForTimeInterval:0.5];
NSLog(@"Barrier: Write complete");
});
// Read operations (concurrent)
for (NSInteger i = 0; i < 3; i++) {
dispatch_async(queue, ^{
NSLog(@"Read %lu: %@", (unsigned long)(i + 3), dataArray);
});
}
// Sync barrier
dispatch_barrier_sync(queue, ^{
NSLog(@"Sync barrier: Clearing data");
[dataArray removeAllObjects];
});
NSLog(@"Data after sync barrier: %@", dataArray);
[NSThread sleepForTimeInterval:1.0];
}
@end
// MARK: - 7. Dispatch Apply
@interface ApplyDemo : NSObject
+ (void)demonstrateApply;
@end
@implementation ApplyDemo
+ (void)demonstrateApply {
NSLog(@"\n--- Dispatch Apply ---");
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
NSLog(@"Processing array with dispatch_apply");
NSArray *data = @[@"Item1", @"Item2", @"Item3", @"Item4", @"Item5"];
dispatch_apply(data.count, queue, ^(size_t index) {
NSString *item = data[index];
NSLog(@"Processing %@ (index: %lu)", item, (unsigned long)index);
[NSThread sleepForTimeInterval:0.2];
});
NSLog(@"All items processed (dispatch_apply blocks until done)");
}
@end
// MARK: - 8. Dispatch Once
@interface OnceDemo : NSObject
+ (void)demonstrateOnce;
@end
@implementation OnceDemo {
static dispatch_once_t onceToken;
static NSString *sharedInstance;
}
+ (void)demonstrateOnce {
NSLog(@"\n--- Dispatch Once ---");
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
for (NSInteger i = 0; i < 5; i++) {
dispatch_async(queue, ^{
dispatch_once(&onceToken, ^{
NSLog(@"Dispatch once executed (should see this only once)");
sharedInstance = @"Singleton Instance";
});
NSLog(@"Iteration %ld, shared instance: %@", (long)i, sharedInstance);
});
}
[NSThread sleepForTimeInterval:1.0];
}
@end
// MARK: - 9. Dispatch I/O
@interface IODemo : NSObject
+ (void)demonstrateIO;
@end
@implementation IODemo
+ (void)demonstrateIO {
NSLog(@"\n--- Dispatch I/O ---");
dispatch_queue_t ioQueue = dispatch_queue_create("com.example.io",
DISPATCH_QUEUE_SERIAL);
dispatch_async(ioQueue, ^{
NSLog(@"Simulating file read...");
[NSThread sleepForTimeInterval:0.5];
NSLog(@"File read complete");
// Process on default queue
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSLog(@"Processing data...");
[NSThread sleepForTimeInterval:0.3];
// Write back on I/O queue
dispatch_async(ioQueue, ^{
NSLog(@"Simulating file write...");
[NSThread sleepForTimeInterval:0.5];
NSLog(@"File write complete");
});
});
});
[NSThread sleepForTimeInterval:2.0];
}
@end
// MARK: - 10. Dispatch Source (Timer)
@interface SourceDemo : NSObject
+ (void)demonstrateSource;
@end
@implementation SourceDemo
+ (void)demonstrateSource {
NSLog(@"\n--- Dispatch Source (Timer) ---");
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
__block NSInteger counter = 0;
dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER,
0,
0,
queue);
dispatch_source_set_timer(timer,
dispatch_time(DISPATCH_TIME_NOW, 0),
500 * NSEC_PER_MSEC, // 500ms
100 * NSEC_PER_MSEC); // 100ms leeway
dispatch_source_set_event_handler(timer, ^{
counter++;
NSLog(@"Timer tick %ld", (long)counter);
if (counter >= 5) {
dispatch_source_cancel(timer);
NSLog(@"Timer cancelled");
}
});
dispatch_resume(timer);
// Wait for timer to complete
[NSThread sleepForTimeInterval:3.0];
}
@end
// MARK: - Main Demonstration
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSLog(@"=== macOS Objective-C Grand Central Dispatch Examples ===\n");
// 1. Basic queues
[GCDBasics demonstrateDispatchQueues];
// 2. Sync vs async
[SyncAsyncDemo demonstrateSyncAsync];
// 3. Delay
[DelayDemo demonstrateDelay];
// 4. Groups
[GroupDemo demonstrateGroups];
// 5. Semaphores
[SemaphoreDemo demonstrateSemaphores];
// 6. Barriers
[BarrierDemo demonstrateBarriers];
// 7. Apply
[ApplyDemo demonstrateApply];
// 8. Once
[OnceDemo demonstrateOnce];
// 9. I/O
[IODemo demonstrateIO];
// 10. Source
[SourceDemo demonstrateSource];
NSLog(@"\n=== GCD Examples Completed ===");
}
return 0;
}