从简单到复杂,每个示例都可以直接在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
...
关键知识点总结
- NSThread: 基础的线程管理,适合简单场景
- 线程同步: @synchronized, NSLock, NSCondition的使用
- GCD:
· 队列类型(串行、并行、主队列、全局队列)
· dispatch_group 任务组
· dispatch_barrier 栅栏函数
· dispatch_semaphore 信号量 - NSOperation:
· 操作依赖
· 队列优先级
· 取消操作 - 实战技巧:
· 缓存机制
· 回调管理
· 并发控制
这个实战项目涵盖了iOS/OSX开发中90%以上的多线程场景,每个示例都可以直接运行观察效果。建议你逐步运行并观察控制台输出,理解每种多线程技术的特点和适用场景。