iOS多线程编程从入门到实战:一份通俗易懂的Objective-C指南

从简单到复杂,每个示例都可以直接在Xcode中运行并看到效果。

一、项目准备

首先在Xcode中创建一个新的macOS Command Line Tool项目,选择Objective-C语言。

二、基础篇:NSThread

示例1:NSThread基本使用

objective-c 复制代码
#import <Foundation/Foundation.h>

@interface SimpleThreadDemo : NSObject
- (void)runBasicExamples;
@end

@implementation SimpleThreadDemo

// 线程执行的方法
- (void)threadTask:(NSDictionary *)info {
    NSString *threadName = info[@"name"];
    for (int i = 0; i < 5; i++) {
        NSLog(@"%@ - 第%d次执行,当前线程:%@", threadName, i + 1, [NSThread currentThread]);
        [NSThread sleepForTimeInterval:1.0]; // 模拟耗时操作
    }
}

- (void)runBasicExamples {
    NSLog(@"=== 1. NSThread基础示例 ===");
    
    // 方法1:使用detachNewThreadSelector创建线程
    [NSThread detachNewThreadSelector:@selector(threadTask:) 
                             toTarget:self 
                           withObject:@{@"name": @"线程A"}];
    
    // 方法2:使用initWithTarget创建线程
    NSThread *threadB = [[NSThread alloc] initWithTarget:self 
                                                selector:@selector(threadTask:) 
                                                  object:@{@"name": @"线程B"}];
    threadB.name = @"自定义线程B";
    [threadB start];
    
    // 方法3:使用performSelectorInBackground
    [self performSelectorInBackground:@selector(threadTask:) 
                           withObject:@{@"name": @"线程C"}];
    
    // 主线程继续执行
    for (int i = 0; i < 3; i++) {
        NSLog(@"主线程执行中... 第%d次", i + 1);
        [NSThread sleepForTimeInterval:0.5];
    }
}

@end

示例2:线程同步和锁

objective-c 复制代码
@interface ThreadSyncDemo : NSObject
@property (atomic, assign) NSInteger atomicCounter;
@property (nonatomic, assign) NSInteger nonatomicCounter;
@property (strong, nonatomic) NSLock *lock;
@property (strong, nonatomic) NSCondition *condition;
@property (assign, nonatomic) BOOL ready;
@end

@implementation ThreadSyncDemo

- (instancetype)init {
    self = [super init];
    if (self) {
        _atomicCounter = 0;
        _nonatomicCounter = 0;
        _lock = [[NSLock alloc] init];
        _condition = [[NSCondition alloc] init];
        _ready = NO;
    }
    return self;
}

// 使用@synchronized关键字
- (void)incrementWithSynchronized {
    @synchronized (self) {
        self.atomicCounter++;
        NSLog(@"原子操作值: %ld, 线程: %@", (long)self.atomicCounter, [NSThread currentThread]);
    }
}

// 使用NSLock
- (void)incrementWithLock {
    [self.lock lock];
    self.nonatomicCounter++;
    NSLog(@"NSLock保护的值: %ld, 线程: %@", (long)self.nonatomicCounter, [NSThread currentThread]);
    [self.lock unlock];
}

// 测试原子性和非原子性
- (void)testAtomicVsNonatomic {
    NSLog(@"\n=== 2. 原子性与非原子性测试 ===");
    
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    
    // 启动多个线程同时修改值
    for (int i = 0; i < 10; i++) {
        dispatch_async(queue, ^{
            for (int j = 0; j < 100; j++) {
                [self incrementWithSynchronized];
                [self incrementWithLock];
            }
        });
    }
    
    // 等待所有操作完成
    [NSThread sleepForTimeInterval:3.0];
    NSLog(@"最终结果 - atomicCounter: %ld, nonatomicCounter: %ld", 
          (long)self.atomicCounter, (long)self.nonatomicCounter);
}

// 生产者-消费者模式演示
- (void)producerConsumerDemo {
    NSLog(@"\n=== 3. 生产者-消费者模式 ===");
    
    // 生产者线程
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        for (int i = 0; i < 5; i++) {
            [self.condition lock];
            NSLog(@"生产者: 生产产品 %d", i + 1);
            self.ready = YES;
            [self.condition signal]; // 唤醒等待的消费者
            [self.condition unlock];
            [NSThread sleepForTimeInterval:1.0];
        }
    });
    
    // 消费者线程
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        for (int i = 0; i < 5; i++) {
            [self.condition lock];
            while (!self.ready) {
                NSLog(@"消费者: 等待产品...");
                [self.condition wait];
            }
            NSLog(@"消费者: 消费产品");
            self.ready = NO;
            [self.condition unlock];
            [NSThread sleepForTimeInterval:0.5];
        }
    });
}

@end

三、进阶篇:GCD

示例3:GCD队列和任务

objective-c 复制代码
@interface GCDDemo : NSObject
- (void)runGCDExamples;
@end

@implementation GCDDemo

- (void)runGCDExamples {
    NSLog(@"\n=== 4. GCD队列演示 ===");
    
    // 串行队列
    dispatch_queue_t serialQueue = dispatch_queue_create("com.example.serial", DISPATCH_QUEUE_SERIAL);
    
    // 并行队列
    dispatch_queue_t concurrentQueue = dispatch_queue_create("com.example.concurrent", DISPATCH_QUEUE_CONCURRENT);
    
    // 主队列
    dispatch_queue_t mainQueue = dispatch_get_main_queue();
    
    // 全局队列
    dispatch_queue_t globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    
    NSLog(@"1. 串行队列演示:任务按顺序执行");
    for (int i = 0; i < 3; i++) {
        dispatch_async(serialQueue, ^{
            NSLog(@"串行任务 %d 开始,线程:%@", i + 1, [NSThread currentThread]);
            [NSThread sleepForTimeInterval:1.0];
            NSLog(@"串行任务 %d 结束", i + 1);
        });
    }
    
    [NSThread sleepForTimeInterval:4.0];
    
    NSLog(@"\n2. 并行队列演示:任务同时执行");
    for (int i = 0; i < 3; i++) {
        dispatch_async(concurrentQueue, ^{
            NSLog(@"并行任务 %d 开始,线程:%@", i + 1, [NSThread currentThread]);
            [NSThread sleepForTimeInterval:1.0];
            NSLog(@"并行任务 %d 结束", i + 1);
        });
    }
    
    [NSThread sleepForTimeInterval:4.0];
}

// 示例4:GCD高级特性
- (void)advancedGCDExamples {
    NSLog(@"\n=== 5. GCD高级特性 ===");
    
    // dispatch_group - 组任务
    dispatch_group_t group = dispatch_group_create();
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    
    NSLog(@"1. dispatch_group演示:等待多个异步任务完成");
    
    for (int i = 0; i < 3; i++) {
        dispatch_group_async(group, queue, ^{
            NSLog(@"组任务 %d 开始", i + 1);
            [NSThread sleepForTimeInterval:arc4random_uniform(3) + 1];
            NSLog(@"组任务 %d 完成", i + 1);
        });
    }
    
    dispatch_group_notify(group, dispatch_get_main_queue(), ^{
        NSLog(@"所有组任务完成!");
    });
    
    [NSThread sleepForTimeInterval:5.0];
    
    // dispatch_barrier - 栅栏任务
    NSLog(@"\n2. dispatch_barrier演示:读写锁模式");
    
    dispatch_queue_t concurrentQueue = dispatch_queue_create("com.example.rwqueue", DISPATCH_QUEUE_CONCURRENT);
    
    // 多个读操作可以并发
    for (int i = 0; i < 3; i++) {
        dispatch_async(concurrentQueue, ^{
            NSLog(@"读操作 %d 开始,线程:%@", i + 1, [NSThread currentThread]);
            [NSThread sleepForTimeInterval:1.0];
            NSLog(@"读操作 %d 完成", i + 1);
        });
    }
    
    // 写操作需要独占
    dispatch_barrier_async(concurrentQueue, ^{
        NSLog(@"=== 写操作开始,独占模式 ===");
        [NSThread sleepForTimeInterval:2.0];
        NSLog(@"=== 写操作完成 ===");
    });
    
    // 继续并发读
    for (int i = 0; i < 3; i++) {
        dispatch_async(concurrentQueue, ^{
            NSLog(@"后续读操作 %d 开始", i + 1);
            [NSThread sleepForTimeInterval:1.0];
            NSLog(@"后续读操作 %d 完成", i + 1);
        });
    }
    
    [NSThread sleepForTimeInterval:8.0];
}

// 示例5:dispatch_semaphore - 信号量控制并发数
- (void)semaphoreDemo {
    NSLog(@"\n=== 6. dispatch_semaphore演示:控制并发数 ===");
    
    dispatch_semaphore_t semaphore = dispatch_semaphore_create(2); // 最多允许2个并发任务
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    
    for (int i = 0; i < 5; i++) {
        dispatch_async(queue, ^{
            dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
            
            NSLog(@"任务 %d 开始执行,当前时间:%@", i + 1, [NSDate date]);
            [NSThread sleepForTimeInterval:2.0];
            NSLog(@"任务 %d 完成", i + 1);
            
            dispatch_semaphore_signal(semaphore);
        });
    }
    
    [NSThread sleepForTimeInterval:12.0];
}

@end

四、高级篇:NSOperation

示例6:NSOperation和NSOperationQueue

objective-c 复制代码
@interface OperationDemo : NSObject
- (void)runOperationExamples;
@end

// 自定义Operation
@interface CustomOperation : NSOperation
@property (copy, nonatomic) NSString *name;
- (instancetype)initWithName:(NSString *)name;
@end

@implementation CustomOperation

- (instancetype)initWithName:(NSString *)name {
    self = [super init];
    if (self) {
        _name = name;
    }
    return self;
}

- (void)main {
    @autoreleasepool {
        if (self.isCancelled) {
            NSLog(@"操作 %@ 已被取消", self.name);
            return;
        }
        
        NSLog(@"操作 %@ 开始执行,线程:%@", self.name, [NSThread currentThread]);
        
        for (int i = 0; i < 3; i++) {
            if (self.isCancelled) {
                NSLog(@"操作 %@ 执行中被取消", self.name);
                return;
            }
            [NSThread sleepForTimeInterval:1.0];
            NSLog(@"操作 %@ 进度:%d/3", self.name, i + 1);
        }
        
        NSLog(@"操作 %@ 完成", self.name);
    }
}

@end

@implementation OperationDemo

- (void)runOperationExamples {
    NSLog(@"\n=== 7. NSOperation基础演示 ===");
    
    // 创建操作队列
    NSOperationQueue *queue = [[NSOperationQueue alloc] init];
    queue.maxConcurrentOperationCount = 2; // 最大并发数
    
    // 创建自定义操作
    CustomOperation *op1 = [[CustomOperation alloc] initWithName:@"操作1"];
    CustomOperation *op2 = [[CustomOperation alloc] initWithName:@"操作2"];
    CustomOperation *op3 = [[CustomOperation alloc] initWithName:@"操作3"];
    CustomOperation *op4 = [[CustomOperation alloc] initWithName:@"操作4"];
    
    // 设置依赖关系:操作2依赖操作1完成
    [op2 addDependency:op1];
    
    // 添加到队列
    [queue addOperations:@[op1, op2, op3, op4] waitUntilFinished:NO];
    
    NSLog(@"所有操作已添加到队列");
    
    [NSThread sleepForTimeInterval:3.0];
    
    // 演示取消操作
    if (!op3.isFinished) {
        [op3 cancel];
        NSLog(@"操作3 已取消");
    }
    
    [NSThread sleepForTimeInterval:5.0];
}

// 示例7:NSOperation的高级用法
- (void)advancedOperationDemo {
    NSLog(@"\n=== 8. NSOperation高级用法:批量处理和进度监控 ===");
    
    NSOperationQueue *queue = [[NSOperationQueue alloc] init];
    
    // 创建一批操作
    NSMutableArray *operations = [NSMutableArray array];
    for (int i = 0; i < 5; i++) {
        NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
            NSLog(@"批量操作 %d 开始,线程:%@", i + 1, [NSThread currentThread]);
            [NSThread sleepForTimeInterval:arc4random_uniform(3) + 1];
            NSLog(@"批量操作 %d 完成", i + 1);
        }];
        operation.name = [NSString stringWithFormat:@"BatchOp-%d", i + 1];
        [operations addObject:operation];
    }
    
    // 设置完成回调
    NSBlockOperation *completionOperation = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"所有批量操作已完成!");
    }];
    
    // 让完成操作依赖所有其他操作
    for (NSOperation *op in operations) {
        [completionOperation addDependency:op];
    }
    
    [operations addObject:completionOperation];
    
    // 添加操作到队列
    [queue addOperations:operations waitUntilFinished:NO];
    
    // 监控队列状态
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        while (queue.operationCount > 0) {
            [NSThread sleepForTimeInterval:0.5];
            NSLog(@"队列中剩余操作数:%lu", (unsigned long)queue.operationCount);
        }
    });
    
    [NSThread sleepForTimeInterval:10.0];
}

@end

五、实战篇:综合应用

示例8:图片下载器(模拟)

objective-c 复制代码
@interface ImageDownloader : NSObject
+ (instancetype)sharedDownloader;
- (void)downloadImageWithURL:(NSString *)urlString 
                   completion:(void(^)(NSData *imageData, NSError *error))completion;
@end

@interface ImageDownloader ()
@property (strong, nonatomic) NSOperationQueue *downloadQueue;
@property (strong, nonatomic) NSCache *imageCache;
@property (strong, nonatomic) NSMutableDictionary *completionHandlers;
@property (strong, nonatomic) NSLock *handlerLock;
@end

@implementation ImageDownloader

+ (instancetype)sharedDownloader {
    static ImageDownloader *instance = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        instance = [[ImageDownloader alloc] init];
    });
    return instance;
}

- (instancetype)init {
    self = [super init];
    if (self) {
        _downloadQueue = [[NSOperationQueue alloc] init];
        _downloadQueue.maxConcurrentOperationCount = 3;
        _imageCache = [[NSCache alloc] init];
        _completionHandlers = [NSMutableDictionary dictionary];
        _handlerLock = [[NSLock alloc] init];
    }
    return self;
}

- (void)downloadImageWithURL:(NSString *)urlString 
                   completion:(void(^)(NSData *imageData, NSError *error))completion {
    
    // 检查缓存
    NSData *cachedImage = [self.imageCache objectForKey:urlString];
    if (cachedImage) {
        NSLog(@"从缓存加载图片:%@", urlString);
        dispatch_async(dispatch_get_main_queue(), ^{
            completion(cachedImage, nil);
        });
        return;
    }
    
    // 存储回调
    [self.handlerLock lock];
    NSMutableArray *handlers = self.completionHandlers[urlString];
    if (!handlers) {
        handlers = [NSMutableArray array];
        self.completionHandlers[urlString] = handlers;
    }
    [handlers addObject:[completion copy]];
    [self.handlerLock unlock];
    
    // 如果已经在下载中,不再重复创建任务
    if (handlers.count > 1) {
        NSLog(@"图片正在下载中,等待回调:%@", urlString);
        return;
    }
    
    // 创建下载任务
    NSBlockOperation *downloadOp = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"开始下载图片:%@", urlString);
        
        // 模拟网络延迟
        [NSThread sleepForTimeInterval:arc4random_uniform(3) + 2];
        
        // 模拟下载数据
        NSData *imageData = [NSString stringWithFormat:@"模拟图片数据 for %@", urlString]
                              .dataUsingEncoding:NSUTF8StringEncoding];
        
        // 模拟随机失败
        BOOL success = arc4random_uniform(10) > 2; // 80%成功率
        
        [self.handlerLock lock];
        NSArray *callbacks = [self.completionHandlers[urlString] copy];
        [self.completionHandlers removeObjectForKey:urlString];
        [self.handlerLock unlock];
        
        if (success) {
            NSLog(@"下载完成:%@", urlString);
            [self.imageCache setObject:imageData forKey:urlString];
            
            dispatch_async(dispatch_get_main_queue(), ^{
                for (void (^callback)(NSData *, NSError *) in callbacks) {
                    callback(imageData, nil);
                }
            });
        } else {
            NSLog(@"下载失败:%@", urlString);
            NSError *error = [NSError errorWithDomain:@"ImageDownloader" 
                                                 code:404 
                                             userInfo:@{NSLocalizedDescriptionKey: @"下载失败"}];
            
            dispatch_async(dispatch_get_main_queue(), ^{
                for (void (^callback)(NSData *, NSError *) in callbacks) {
                    callback(nil, error);
                }
            });
        }
    }];
    
    [self.downloadQueue addOperation:downloadOp];
}

@end

示例9:测试代码

objective-c 复制代码
// main.m
#import <Foundation/Foundation.h>
#import "SimpleThreadDemo.h"
#import "ThreadSyncDemo.h"
#import "GCDDemo.h"
#import "OperationDemo.h"
#import "ImageDownloader.h"

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        NSLog(@"=== Objective-C 多线程实战演示 ===\n");
        
        // 基础篇
        SimpleThreadDemo *demo1 = [[SimpleThreadDemo alloc] init];
        [demo1 runBasicExamples];
        
        [NSThread sleepForTimeInterval:5.0];
        
        // 同步篇
        ThreadSyncDemo *demo2 = [[ThreadSyncDemo alloc] init];
        [demo2 testAtomicVsNonatomic];
        [demo2 producerConsumerDemo];
        
        [NSThread sleepForTimeInterval:10.0];
        
        // GCD篇
        GCDDemo *demo3 = [[GCDDemo alloc] init];
        [demo3 runGCDExamples];
        [demo3 advancedGCDExamples];
        [demo3 semaphoreDemo];
        
        [NSThread sleepForTimeInterval:15.0];
        
        // NSOperation篇
        OperationDemo *demo4 = [[OperationDemo alloc] init];
        [demo4 runOperationExamples];
        [demo4 advancedOperationDemo];
        
        [NSThread sleepForTimeInterval:10.0];
        
        // 实战篇:图片下载器测试
        NSLog(@"\n=== 9. 实战:图片下载器测试 ===");
        
        ImageDownloader *downloader = [ImageDownloader sharedDownloader];
        
        NSArray *urls = @[
            @"https://example.com/image1.jpg",
            @"https://example.com/image2.jpg",
            @"https://example.com/image3.jpg",
            @"https://example.com/image1.jpg", // 重复URL测试缓存
            @"https://example.com/image4.jpg"
        ];
        
        for (NSString *url in urls) {
            [downloader downloadImageWithURL:url completion:^(NSData *imageData, NSError *error) {
                if (error) {
                    NSLog(@"回调 - 下载失败 %@: %@", url, error.localizedDescription);
                } else {
                    NSLog(@"回调 - 下载成功 %@: 数据大小 %lu bytes", url, (unsigned long)imageData.length);
                }
            }];
        }
        
        // 等待所有操作完成
        [NSThread sleepForTimeInterval:15.0];
        
        NSLog(@"\n=== 所有演示完成 ===");
    }
    return 0;
}

运行效果

在Xcode中运行这个项目,你将在控制台看到类似这样的输出:

复制代码
=== Objective-C 多线程实战演示 ===

=== 1. NSThread基础示例 ===
主线程执行中... 第1次
线程A - 第1次执行,当前线程:<NSThread: ...>
线程B - 第1次执行,当前线程:<NSThread: ...>
...

=== 2. 原子性与非原子性测试 ===
原子操作值: 1, 线程: <NSThread: ...>
...

=== 3. 生产者-消费者模式 ===
生产者: 生产产品 1
消费者: 等待产品...
...

=== 4. GCD队列演示 ===
1. 串行队列演示:任务按顺序执行
...

=== 9. 实战:图片下载器测试 ===
开始下载图片:https://example.com/image1.jpg
开始下载图片:https://example.com/image2.jpg
...

关键知识点总结

  1. NSThread: 基础的线程管理,适合简单场景
  2. 线程同步: @synchronized, NSLock, NSCondition的使用
  3. GCD:
    · 队列类型(串行、并行、主队列、全局队列)
    · dispatch_group 任务组
    · dispatch_barrier 栅栏函数
    · dispatch_semaphore 信号量
  4. NSOperation:
    · 操作依赖
    · 队列优先级
    · 取消操作
  5. 实战技巧:
    · 缓存机制
    · 回调管理
    · 并发控制

这个实战项目涵盖了iOS/OSX开发中90%以上的多线程场景,每个示例都可以直接运行观察效果。建议你逐步运行并观察控制台输出,理解每种多线程技术的特点和适用场景。

相关推荐
for_ever_love__2 小时前
Objective-C学习 NSArray 和 NSMutableArray 功能详解
学习·ios·objective-c
ITKEY_2 小时前
flutter打包ipad 并上传Appstore
flutter·ios·ipad
SY.ZHOU20 小时前
大型工程跨全平台实践总结
flutter·ios·安卓·鸿蒙
denggun123451 天前
Sendable 协议-Swift 结构化并发的核心安全保障
ios·swift
奶糖的次元空间1 天前
iOS 学习笔记 - 创建第一个APP
ios
for_ever_love__1 天前
Objective-C 学习 NSString 和 NSMutableString的基本功能详解
学习·ios·objective-c
@大迁世界1 天前
注意,苹果刚刚做出改变: iOS 26.4 系统强制所有设备开启“被盗设备保护”功能。
macos·ios·objective-c·cocoa
卢锡荣2 天前
LDR6021Q 车规级 Type‑C PD 控制芯片:一芯赋能,边充边传,稳驭全场景
c语言·开发语言·ios·计算机外设·电脑
2501_907136822 天前
iOS任意版本号APP下载
ios·软件需求