1. pthread
- pthread是一套通用的多线程的 API,可以在Unix / Linux / Windows 等系统跨平台使用,使用 C 语言编写,需要程序员自己管理线程的生命周期,使用难度较大,在 iOS 开发中几乎不使用 pthread
2. NSThread
NSThread 是苹果官方提供的,使用起来比 pthread 更加面向对象,简单易用,可以直接操作线程对象。 不过也需要需要程序员自己管理线程的生命周期(主要是创建),我们在开发的过程中偶尔使用 NSThread。
- 获取当前线程
[NSThread currentThread];
- 先创建线程,在启动
NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(run) object:NULL];
[thread start];
- 创建线程后自启动线程
[NSThread detachNewThreadSelector:@selector(run) toTarget:self withObject:NULL];
- 创建并启动线程
[self performSelectorInBackground:@selector(run) withObject:NULL];
- NSThread相关方法
// 获得主线程
+ (NSThread *)mainThread;
// 判断是否为主线程(对象方法)
- (BOOL)isMainThread;
// 判断是否为主线程(类方法)
+ (BOOL)isMainThread;
// 获得当前线程
NSThread *current = [NSThread currentThread];
// 线程的名字——setter方法
- (void)setName:(NSString *)n;
// 线程的名字——getter方法
- (NSString *)name;
- NSThread控制
#启动线程
- (void)start;
#阻塞(暂停)线程
+ (void)sleepUntilDate:(NSDate *)date;
+ (void)sleepForTimeInterval:(NSTimeInterval)ti;
#强制停止线程
+ (void)exit;
- 线程之间通信 在开发中,我们经常会在子线程进行耗时操作,操作结束后再回到主线程去刷新 UI。这就涉及到了子线程和主线程之间的通信
#在主线程上执行操作
- (void)performSelectorOnMainThread:(SEL)aSelector withObject:(id)arg waitUntilDone:(BOOL)wait;
- (void)performSelectorOnMainThread:(SEL)aSelector withObject:(id)arg waitUntilDone:(BOOL)wait modes:(NSArray<NSString *> *)array;
#在指定线程上执行操作
- (void)performSelector:(SEL)aSelector onThread:(NSThread *)thr withObject:(id)arg waitUntilDone:(BOOL)wait modes:(NSArray *)array NS_AVAILABLE(10_5, 2_0);
- (void)performSelector:(SEL)aSelector onThread:(NSThread *)thr withObject:(id)arg waitUntilDone:(BOOL)wait NS_AVAILABLE(10_5, 2_0);
#在当前线程上执行操作,调用 NSObject 的 performSelector:相关方法
- (id)performSelector:(SEL)aSelector;
- (id)performSelector:(SEL)aSelector withObject:(id)object;
- (id)performSelector:(SEL)aSelector withObject:(id)object1 withObject:(id)object2;
- 下面是一个子线程下载图片,主线程展示图片
-(void)downloadImageOnThread
{
// 在子线程下载图片
[NSThread detachNewThreadSelector:@selector(downloadImage) toTarget:self withObject:NULL];
}
-(void)downloadImage
{
NSURL *imageUrl = [[NSURL alloc] initWithString:@"https://ysc-demo-1254961422.file.myqcloud.com/YSC-phread-NSThread-demo-icon.jpg"];
NSData *imageData = [NSData dataWithContentsOfURL:imageUrl];
self.image = [UIImage imageWithData:imageData];
// 回到主线程展示图片
[self performSelectorOnMainThread:@selector(refreshOnMainThread:) withObject:self waitUntilDone:YES];
}
-(void)refreshOnMainThread:(UIImage *)image
{
self.imageView.image = image;
}
- 经典卖票案例
/*
* 设置20张票和AB两个窗口
*/
-(void)initSaleSiticket
{
self.ticketCount = 20;
// A窗口卖票线程
self.saleWindowA = [[NSThread alloc] initWithTarget:self selector:@selector(saleSicketAction) object:NULL];
self.saleWindowA.name = @"A窗口";
// B窗口卖票线程
self.saleWindowB = [[NSThread alloc] initWithTarget:self selector:@selector(saleSicketAction) object:NULL];
self.saleWindowB.name = @"B窗口";
// 开始卖票
[self.saleWindowA start];
[self.saleWindowB start];
}
-(void)saleSicketAction
{
while (YES) {
[self.lock lock];
if (self.ticketCount > 0) {
self.ticketCount--;
NSLog(@"%@ : %ld",[NSThread currentThread].name,(long)self.ticketCount);
} else {
NSLog(@"票卖完了");
break;
}
[self.lock unlock];
[NSThread sleepForTimeInterval:1.0];
}
}