上一节我们了解了那么多的有关多线程的理解,接下来我会一一写每一个开辟子线程的代码,演示怎么使用,光说不练,就是笨蛋,别光看,伸出双手,我们一起撸啊撸!
第一种方法:pthread
#import "ViewController.h"
#import <pthread.h>
@interface ViewController ()
@end
@implementation ViewController
void *download(void *data)
{
//耗时操作
for (int i = 0; i < 100000; i++)
{
NSLog(@"thread = %@",[NSThread currentThread]);
}
return NULL;
}
- (void)viewDidLoad {
[super viewDidLoad];
//创建线程
pthread_t myThread;
pthread_create(&myThread, NULL, download, NULL);
}
@end
第二种方法:NSTread,补充一下,只要子线程结束以后就死了,不能复生了,和人死了一样,人死不能复生;
#import "ViewController.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
}
//方法一
- (void)download
{
//耗时操作
for (int i = 0; i < 10000; i++)
{
NSLog(@"download = %@",[NSThread currentThread]);
}
}
//方法二
- (void)download2
{
//耗时操作
for (int i = 0; i < 10000; i++)
{
NSLog(@"download2 = %@",[NSThread currentThread]);
}
}
//方法三
- (void)download3
{
//耗时操作
for (int i = 0; i < 10000; i++)
{
NSLog(@"download3 = %@",[NSThread currentThread]);
}
}
//点击屏幕执行的方法
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
//创建子线程:方法一
NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(download) object:nil];
[thread start];
//创建子线程:方法二
[NSThread detachNewThreadSelector:@selector(download2) toTarget:self withObject:nil];
//创建子线程:方法三
[self performSelectorInBackground:@selector(download3) withObject:nil];
}
@end
第三种方法:GCD
补充一下:
dispatch_sync :同步,不具备开线程的能力;
dispatch_async :异步,具备开线程的能力;
串行队列:一个任务执行完后,再执行下一个任务;
并发队列:多个任务可以同时执行;
那么问题来了,既然就有四种处理方法:
- 同步--串行队列(很少用);
- 同步--并行队列(很少用);
- 异步--串行队列(有时用);
- 异步--并行队列(常用);
代码如下:
#import "ViewController.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
}
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
dispatch_queue_t gQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(gQueue, ^{
//耗时处理;
for (int i = 0 ; i < 1000; i++)
{
NSLog(@"我最耗时-----%@",[NSThread currentThread]);
}
});
dispatch_async(gQueue, ^{
//耗时处理;
for (int i = 0 ; i < 1000; i++)
{
NSLog(@"我最耗时-----%@",[NSThread currentThread]);
}
});
dispatch_async(gQueue, ^{
//耗时处理;
for (int i = 0 ; i < 1000; i++)
{
NSLog(@"我最耗时-----%@",[NSThread currentThread]);
}
});
dispatch_async(gQueue, ^{
//耗时处理;
for (int i = 0 ; i < 1000; i++)
{
NSLog(@"我最耗时-----%@",[NSThread currentThread]);
}
});
}
@end
第四种方法:NSOperationQueue
这里涉及到线程通信;
#import "ViewController.h"
@interface ViewController ()
@property (nonatomic,strong) NSOperationQueue *queue;
@end
@implementation ViewController
-(NSOperationQueue *)queue
{
if (!_queue)
{
_queue = [[NSOperationQueue alloc] init];
}
return _queue;
}
- (void)viewDidLoad {
[super viewDidLoad];
NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
int count = 100000;
for (int i = 0; i < 10000; i++)
{
NSLog(@"我最耗时 = %@",[NSThread currentThread]);
count--;
}
//线程通讯,到主线程执行打印count
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
NSLog(@"执行完啦 = %d",count);
}];
}];
[self.queue addOperation:operation];
}
@end
扩充:对多线程安全访问统一资源安全问题:
代码:
#import "ViewController.h"
@interface ViewController ()
/**
* 模拟买票,剩余票数
*/
@property (nonatomic,assign) int ticketCount;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
//比如剩余 10 张票
self.ticketCount = 10;
}
- (void)saleTicket
{
while (1)
{
//解决线程安全
@synchronized(self)
{
int count = self.ticketCount;
if (count > 0)
{
self.ticketCount = count - 1;
NSLog(@"买一张,剩余 %d 张",self.ticketCount);
}
else
{
return;
}
}
}
}
//点击屏幕执行的方法
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
//创建子线程:方法一
NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(saleTicket) object:nil];
[thread start];
//创建子线程:方法二
[NSThread detachNewThreadSelector:@selector(saleTicket) toTarget:self withObject:nil];
//创建子线程:方法三
[self performSelectorInBackground:@selector(saleTicket) withObject:nil];
}
@end
如果转载请注明转于:
AirZilong的博客