一个线程就是一个任务的执行
/*
什么是进程:系统分配资源的最小单位(一个APP运行时在内存中所需要的所有资源)
什么是线程:cup运行的最小基本单位,一个线程就是一个任务
有什么区别: 1.一个进程可以包含多个线程,系统至少会为APP开辟一个进程,一个进程至少会有一个线程(主线程)
2.每个进程有自己独立的堆栈空间,一个进程奔溃(死掉)不会影响其他进程
3.线程没有自己独立的堆栈空间,统一使用进程的内存空间,一个线程死掉,整个进程都会死掉
多线程的实质:CPU快速的在各个线程之间切换,由于CPU的执行速度很快,我们根本感觉不到,就相当于多个任务同时执行,这也是为什么我们的电脑开得程序过多就会感觉性能下降的原因。
*/
#pragma mark 点击按钮执行的方法
- (IBAction)doButton:(id)sender {
//查看当前是否在主线程
// NSLog(@"%d",[[NSThread currentThread] isMainThread]);
//线程阻塞(UI冻结)
/*
//INTMAX_MAX是支持的最大整形数字
//单一线程容易造成UI冻结
for (NSInteger i =0; i < INTMAX_MAX; i++) {
NSLog(@"卡死了");
}
*/
//1.开辟子线程的第一种方式*********************
/*
//object:通常使用object来完成从主线程向子线程传值的对象
NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(doThread1:) object:@"123"];
//线程的优先级
thread.threadPriority = 0.8;
//用这种方式创建的多线程需要手动开启
[thread start];
NSThread *thread2 = [[NSThread alloc] initWithTarget:self selector:@selector(doThread2:) object:nil];
//
thread2.threadPriority = 0.1;
thread2.name = @"窗口2";
[thread2 start];
*/
//2.第二种方式开辟子线程的方式******************
//该方法不需要手动开启
[NSThread detachNewThreadSelector:@selector(doThread3:) toTarget:self withObject:nil];
//3.线程之间的互斥**************************
//线程互斥:因为线程没有自己独立的堆栈空间,都是使用进程的空间,所以有可能多个线程访问进程的同一块资源,这就会出现线程访问问题,多个线程访问同一个资源就叫做线程互斥,解决办法就是加线程锁
//加线程锁
NSLock *l =[[NSLock alloc] init];
NSThread *th1 = [[NSThread alloc] initWithTarget:self selector:@selector(doTh1:) object:l];
NSThread *th2 = [[NSThread alloc] initWithTarget:self selector:@selector(doTh1:) object:l];
NSThread *th3 = [[NSThread alloc] initWithTarget:self selector:@selector(doTh1:) object:l];
[th1 start];
[th2 start];
[th3 start];
/*
for (int i = 0; i < 100; i++) {
NSLog(@"主线程******");
}
*/
}
/*
-(void)doThread1:(id)object
{
//因为在子线程中也需要做内存管理,而在MRC中用autorelease修饰的对象,需要自动释放池来释放对象,在子线程中,系统没有为我们创建自动释放池,需要我们自己手动创建一个自动释放池
@autoreleasepool {
//该方法内部就是子线程
NSLog(@"th1 =%d",[[NSThread currentThread] isMainThread]);
NSLog(@"%@",object);
for (int i = 0; i<100; i++) {
NSLog(@"******子线程");
}
}
}
*/
#pragma mark 第二个子线程执行的方法
/*
-(void)doThread2:(id)object
{
@autoreleasepool {
NSLog(@"%@",[[NSThread currentThread] name]);
for (int i = 0; i < 100; i++) {
NSLog(@"***子线程二****");
}
}
}
*/
#pragma mark 第三个子线程执行的方法
-(void)doThread3:(id)object
{
NSURL *url = [NSURL URLWithString:BaseUrl];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
UIImage *image = [UIImage imageWithData:data];
//不建议在Ui更新在子线程中写,因为子线程更新UI会存在潜在问题,并且耗时,费性能
// self.imageView.image = image;
//从子线程回到主线程的方法(主要用于线程间的通信)
//waitUntilDone如果是YES就立刻跳转到主线程执行,执行完毕后再跳转回来接着执行下面的代码,如果NO,就行先把整个子线程的方法执行完毕后,再跳转到主线程执行
[self performSelectorOnMainThread:@selector(doMainThread:) withObject:image waitUntilDone:YES];
// NSLog(@"11111111111111111111111111111111111111111111111");
/*
for (int i = 0; i < 100; i++) {
NSLog(@"******************************线程三**");
}
*/
}
#pragma mark -该方法是从子线程中回到主线程的方法
-(void)doMainThread:(id)object
{
self.imageView.image = object;
// NSLog(@"000000000oooooooooooooooooooo=%d",[[NSThread currentThread] isMainThread]);
}
-(void)doTh1:(id)object
{
NSLock *l = (NSLock *)object;
while (true) {
[l lock];
//假设有一百张票
static int num = 100;
num--;
sleep(2);
NSLog(@"num=%d",num);
if (num==0) {
break;
}
[l unlock];
}
}
@end
//
// UIImageView+CreateByUrl.m
// Lesson22多线程下载
//
//
//
//
#import "UIImageView+CreateByUrl.h"
@implementation UIImageView (CreateByUrl)
-(void)setImageByUrl:(NSString *)urlString
{
//在block内部使用的变量
__block UIImageView *weakSelf = self;
//创建一个子线程队列来做数据请求
dispatch_queue_t downLoadQueue =dispatch_queue_create("downLoad", NULL);
//创建一个子线程
dispatch_async(downLoadQueue, ^{
NSURL *url = [NSURL URLWithString:urlString];
//同步
NSData *data = [NSData dataWithContentsOfURL:url];
//用请求回来的数据创建一个image
UIImage *image = [UIImage imageWithData:data];
//回到主线程
dispatch_sync(dispatch_get_main_queue(), ^{
//主线程更新UI
weakSelf.image = image;
});
});
}
@end
/ ViewController.m
// Lesson22-多线程队列
//
//
#import "ViewController.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// ***********NSObject******
// [self performSelectorInBackground:@selector(doThread1:) withObject:@"123"];
//***********************2.NSOperationQueue********
//1.创建一个线程对列
NSOperationQueue *operation = [[NSOperationQueue alloc] init];
//2.在线程队列里面创建多线程
[operation addOperationWithBlock:^{
//在block内部就是一个子线程
// NSLog(@"block = %d",[[NSThread currentThread] isMainThread]);
//返回主线程
// [self performSelectorOnMainThread:@selector(aaaa:) withObject:nil waitUntilDone:YES];
}];
//*****3.NSOperationQueue
//1.创建队列
NSOperationQueue * op = [[NSOperationQueue alloc] init];
//创建子线程对象
NSInvocationOperation *inv = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(doOp1:) object:nil];
inv.queuePriority = NSOperationQueuePriorityVeryHigh;
//(优先级)效果不明显
NSInvocationOperation *inv2 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(doOp2:) object:nil];
inv2.queuePriority = NSOperationQueuePriorityVeryLow;
//将子线程添加到线程队列
[op addOperation:inv];
[op addOperation:inv2];
//**************4.GCD(C语言)
/*
//1.创建一个队列
//参数一:线程队列的名字
//参数二:要创建线程队列的类型(串行,并行)
dispatch_queue_t queue = dispatch_queue_create("GCD", NULL);
//2.在队列里面创建子线程
//参数一:子线程创在哪个队列里,参数二,block里面就是子线程
dispatch_async(queue, ^{
//子线程
NSLog(@"queue=%d",[[NSThread currentThread] isMainThread]);
//回到主线程的方法dispatch_get_main_queue()
dispatch_sync(dispatch_get_main_queue(), ^{
NSLog(@"sync=%d",[[NSThread currentThread] isMainThread]);
});
});
*/
//5.***5GCD线程队列的串行
/*
//默认是串行队列,串行队列的特点:队列里面的子线程是顺序执行的
dispatch_queue_t serialQueue = dispatch_queue_create("serialQueue", DISPATCH_QUEUE_SERIAL);
dispatch_async(serialQueue, ^{
for (int i =0; i < 10; i++) {
NSLog(@"11111");
}
});
dispatch_async(serialQueue, ^{
for (int i = 0; i < 10; i++) {
NSLog(@"22222222");
}
});
*/
//6.*****GCD并行******
//DISPATCH_QUEUE_CONCURRENT表示并行队列 并行队列的特点:受队列管理的子线程是并发执行的
dispatch_queue_t concurrent = dispatch_queue_create("concurrent", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(concurrent, ^{
for (int i = 0; i < 10; i++) {
NSLog(@"11111111111");
}
});
dispatch_async(concurrent, ^{
for (int i = 0; i < 10; i++) {
NSLog(@"2222");
}
});
}
/*
-(void)doThread1:(id)object
{
NSLog(@"dothread=%d",[[NSThread currentThread] isMainThread]);
}
*/
-(void)doOp1:(id)object
{
/*
for (int i =0 ; i < 100; i++) {
NSLog(@"op1 *******");
}
*/
}
-(void)doOp2:(id)object
{
/*
for (int i =0 ; i < 100; i++) {
NSLog(@" ==================op2");
}
*/
}