进程:内存里的一个程序就是一个进程,运行起来的程序就是一个进程,程序并不能单独运行,只有将程序装载到内存中,系统为它分配资源才能运行,每个进程均运行在其专用且受保护的内存空间内,而这种执行的程序就称之为进程。程序和进程的区别就在于:程序是指令的集合,它是进程运行的静态描述文本;进程是程序的一次执行活动,属于动态概念。
线程:线程是指进程内的一个执行单元,也是进程内的可调度实体,一个应用至少有一个线程(主线程)(IOS中UI主线程)
iOS有三种多线程编程的技术,分别是:
(一)NSThread
(二)Cocoa NSOperation
(三)GCD(全称:Grand Central Dispatch)
这三种编程方式从上到下,抽象度层次是从低到高的,抽象度越高的使用越简单,也是Apple最推荐使用的。
-(void)downloadImage:(NSString *) url{ NSData *data = [[NSData alloc] initWithContentsOfURL:[NSURL URLWithString:url]]; UIImage *image = [[UIImage alloc] initWithData:data]; if(image == nil){ } else{ [self performSelectorOnMainThread:@selector(updateUI:) withObject:image waitUntilDone:YES]; } } -(void)updateUI:(UIImage*) image{ self.imageView.image = image; } - (void)viewDidLoad { [super viewDidLoad]; // [NSThread detachNewThreadSelector:@selector(downloadImage:) toTarget:self withObject:kURL]; NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(downloadImage:) object:kURL]; [thread start]; }
使用 NSOperation的方式有两种,一种是用定义好的两个子类:NSInvocationOperation 和 NSBlockOperation。另一种是继承NSOperation。
- (void)viewDidLoad{ [super viewDidLoad]; NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(downloadImage:) object:kURL]; NSOperationQueue *queue = [[NSOperationQueue alloc] init]; [queue addOperation:operation]; } -(void)downloadImage:(NSString *)url{ NSURL *nsUrl = [NSURL URLWithString:url]; NSData *data = [[NSData alloc] initWithContentsOfURL:nsUrl]; UIImage * image = [[UIImage alloc] initWithData:data]; [self performSelectorOnMainThread:@selector(updateUI:) withObject:image waitUntilDone:YES]; } -(void)updateUI:(UIImage*) image{ self.imageView.image = image; }
什么是GCD?
全称是Grand Central Dispatch,纯C语言,提供了非常多强大的函数
GCD的优势
dispatch_queue_t queue =dispatch_queue_create(NULL, DISPATCH_QUEUE_CONCURRENT); dispatch_async(queue, ^{ //1.获取网址字符串 NSString * urlString = @"http://www.bz55.com/uploads/allimg/121230/1-121230094954.jpg"; //2.NSString->NSURL NSURL * url = [NSURL URLWithString:urlString]; //3.同步下载 NSData * data = [NSData dataWithContentsOfURL:url]; UIImage * image = [UIImage imageWithData:data]; dispatch_sync(dispatch_get_main_queue(), ^{ self.view.backgroundColor = [UIColor colorWithPatternImage:image]; }); });
P.S.
子线程里面不能更行主线程的UI
只有主线程能够更新UI,其他都不行
子线程没有能力去更新主线程的UI,我们之所以能够看到某些时候更新了的效果,是因为子线程结束,立刻回到了主线程中,主线程更新子线程里面要求的UI,由于子线程结束回到主线程的时间比较短,因此造成了一种误解,以为是子线程更新了UI,实则是UI主线程自己做的
如果在子线程里面直接更新UI, 可能会造成两种错误
a. UI的更新不及时,必须等子线程结束了,主线程才会去更新UI
b. 当子线程还没有结束,主线程中已经将UI元素释放,那么当子线程结束了,回到主线程中,就会去继续更新这个UI元素,可是UI已经没有了,造成内存错误
当子线程执行完毕,立刻返回到主线程,如果子线程有需要让主线程做一定的事情,那么主线程会挂起其他的任务,执行这些事情
参考资料
关于iOS多线程,你看我就够了
iOS开发多线程篇—GCD介绍
iOS多线程编程之Grand Central Dispatch(GCD)介绍和使用
联系客服