加锁前后示意图

  • 一个程序进入内存运行时就成了一个进程,一个进程包含若干线程,其中必有一个主线程.线程之间运行是独立的.

  • 多线程优势

  1. 线程之间容易共享内存,进程间不能.
  2. 充分发挥多核处理器的优势,不同任务分配给不同处理器,进入“并行运算”的状态
  3. 将耗时、轮询或并发需求高的任务分配到其他线程进行,主线程负责统一更新界面,这样使用户体验更好.
  • 多线程劣势
  1. 占内存(默认住线程1M 子线程512K)
  2. CPU开销大(一般同时开启线程小于5个).
  3. 程序设计变得复杂.
  • 多线程状态1.新建:分配内存,初始化内部成员变量的值2.就绪:创建方法调用的栈和计数器3.运行:运行状态4.终止:线程终止5.阻塞:线程需要暂停一段时间

  • pthread1.跨平台,可移植2.使用难度大3.C语言

  • NSThread1.面向对象2.直接操作线程对象3.Objective-C

  • 金沙网址,GCD1.替代NSThread2.充分利用多核技术3.C语言

  • NSOperation1.基于GCD,更简单2.更面向对象3.Objective-C

在storyboard里放一个Button和一个Text View(用来测试线程的阻塞)

  • 线程一启动就会执行selfrun:方法
  • 测试阻塞线程时,由于test方法处在主线程,Debug栏一直输出,所以拖动文本视图没有任何反应.

#import "ViewController.h"@interface ViewController ()@end@implementation ViewController- viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib.}- didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated.}//获取当前、主线程- ClickBtn:sender { NSThread *current = [NSThread currentThread]; NSLog(@"Current thread %@ ",current); NSThread *main = [NSThread mainThread]; NSLog(@"Main thread %@",main); [self threadCreate1]; //第二种方法 [self threadCreate2]; //第三种方法 [self threadCreate3]; //测试阻塞方法 [self threadTest];}//输出当前线程- run:(NSString *)param{ NSThread *current = [NSThread currentThread]; for(int i = 0; i<10; i++){ NSLog(@"%@ run %@",current,param); }}- threadCreate1{ NSThread *threadA =[[NSThread alloc]initWithTarget:self selector:@selector object:@"线程A参数"]; threadA.name = @"线程A"; [threadA start]; NSThread *threadB =[[NSThread alloc]initWithTarget:self selector:@selector object:@"线程B参数"]; threadB.name = @"线程B"; [threadB start];}- threadCreate2{ [NSThread detachNewThreadSelector:@selector toTarget:self withObject:@"方式2参数"];}//隐式创建并启动线程,在后台线程中执行- threadCreate3{ [self performSelectorInBackground:@selector withObject:@"方式3参数"];}//测试阻塞线程- threadTest{ NSLog(@"%@",[NSThread currentThread]); for (int i=0 ; i<10000; i++) { NSLog(@"-----%d",i); }} @end
  • 线程共享会造成资源抢夺,引起数据错乱及安全问题

金沙网址 1加锁前后示意图

  • 使用 @synchronized 修饰同步代码块

  • 主线程的方法
    performSelectorOnMainThread: withObject: waitUntilDone:
  • 子线程的方法
    performSelector: onThread:(NSThread *) withObject: waitUntilDone:

  • 基于C语言
  • 系统完全管理线程, 无需编写线程代码

  • 将长期运行任务拆成多个工作单元并添加到队列中,系统代为管理并放到多个线程上执行
  • FIFO原则,先进队列先处理,但由于执行时间不同,不一定先结束
  • 分类:1.Serial Dispatch Queue:
    底层线程池只有一个线程,一次执行一个任务,执行完一个任务才能执行下一个2.Concurrent
    Dispatch Queue: 底层线程池有多个线程,按FIFO原则执行多任务
1.获取全局并发队列(Global Concurrent Dispatch Queue)
  • 全局并发队列可以按FIFO顺序并行执行多个任务
  • dispatch_get_global_queue(long identifier, unsigned long flags)获取队列第一个参数用于指定队列优先级,含4个宏定义常量:#define DISPATCH_QUEUE_PRIORITY_HIGH 2 //高``#define DISPATCH_QUEUE_PRIORITY_DEFAULT 0 //默认``#define DISPATCH_QUEUE_PRIORITY_LOW //低``#define DISPATCH_QUEUE_PRIORITY_BACKGROUND INT16_MIN //后台
2.创建串、并行队列(Serial And Concurrent Dispatch Queue)
  • 创建队列dispatch_queue_t``dispatch_queue_create(const char * label, dispatch_queue_attr_t attr)第一个参数表示队列的字符串第二个参数控制串并发队列(设为NULL默认串行):DISPATCH_QUEUE_SERIAL //串行``DISPATCH_QUEUE_CONCURRENT //并行
3.获取主队列
  • 主队列在主线程中执行
  • dispatch_get_main_queue()获取主队列
1.同步添加任务到队列,不具备开启新线程能力,阻塞调用线程直到相应任务完成
  • 调用函数dispatch_sync(dispatch_queue_t queue, ^block) //代码块``dispatch_sync_f(dispatch_queue_t queue, void *context, dispatch_function_t work) //函数
2.异步在新线程执行任务,可以让线程池立即执行,调用其他线程做其他事情,应尽可能使用异步.
  • 调用函数:dispatch_async(dispatch_queue_t queue, ^block) //代码块``dispatch_async_f(dispatch_queue_t queue, void *context, dispatch_function_t work) //函数
  • 在storyboard放两个Button分别执行串、并行任务

#import "ViewController.h"@interface ViewController ()@end@implementation ViewControllerdispatch_queue_t serialQueue;dispatch_queue_t globalQueue;- viewDidLoad { [super viewDidLoad]; //创建串行队列 serialQueue = dispatch_queue_create("serQ", DISPATCH_QUEUE_SERIAL); //全局并发队列 globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);}- didReceiveMemoryWarning { [super didReceiveMemoryWarning];}//串行异步执行任务- asynSerial:sender { dispatch_async(serialQueue, ^{ for (int i = 0; i<10; i++) { NSLog(@"%@ task1 %d",[NSThread currentThread],i); } }); dispatch_async(serialQueue, ^{ for (int i = 0; i<10; i++) { NSLog(@"%@ task2 %d",[NSThread currentThread],i); } });}//并行异步执行任务- asynConcurrent:sender { dispatch_async(globalQueue, ^{ for (int i = 0; i<10; i++) { NSLog(@"%@ task1 %d",[NSThread currentThread],i); } }); dispatch_async(globalQueue, ^{ for (int i = 0; i<10; i++) { NSLog(@"%@ task2 %d",[NSThread currentThread],i); } });}@end
  • 单次执行dispatch_once(dispatch_once_t * predicate, ^block)
  • 多次执行dispatch_apply(size_t iterations, dispatch_queue_t queue, ^block)

  • 将多个block组成一组,监听此组任务是否全部完成.1.创建队列组对象dispatch_group_create()2.调度队列组dispatch_group_async()3.通知:任务执行完后通知执行其他操作dispatch_group_notify()

  • NSOperation实例代表一个多线程任务

新建一个继承NSOperation的类.

//Download.h#import <Foundation/Foundation.h>#import <UIKit/UIKit.h>@class Download;//定义代理@protocol DownloadDelegate <NSObject>//下载方法- download:(Download *)operation image:(UIImage *)image;@end@interface Download : NSOperation@property (nonatomic, strong)NSString *url;//代理属性@property (nonatomic, weak)id<DownloadDelegate>delegate;@end

//Download.m#import "Download.h"@implementation Download//重写main方法- main{ @autoreleasepool { NSURL *url = [NSURL URLWithString:self.url]; NSData *data = [NSData dataWithContentsOfURL:url]; UIImage *image = [UIImage imageWithData:data]; [[NSOperationQueue mainQueue]addOperationWithBlock:^{ NSLog(@"download finished"); if ([self.delegate respondsToSelector:@selector(download:image:)]) { [self.delegate download:self image:image]; } }]; }}@end

在storyboard中放一个Image View

//ViewController.m#import "ViewController.h"#import "Download.h"@interface ViewController ()<DownloadDelegate>@property (strong, nonatomic) IBOutlet UIImageView *imageView;@end@implementation ViewController- viewDidLoad { [super viewDidLoad]; //创建队列 NSOperationQueue *queue = [[NSOperationQueue alloc]init]; //下载操作 Download *operation = [[Download alloc]init]; operation.delegate = self; operation.url =@"https://mir-s3-cdn-cf.behance.net/project_modules/max_1200/943ff442182699.57c4298d2eb2a.png" ; //操作加到队列中 [queue addOperation:operation];}//执行操作- download:(Download *)operation image:(UIImage *)image{ self.imageView.image = image;}- didReceiveMemoryWarning { [super didReceiveMemoryWarning];}@end

金沙网址 2运行结果

若提示:App Transport security has blocked a cleartext HTTP resource load
since it is insecure. Temporary exceptions can be configured via your
app’s Info.plist file.解决方法:

金沙网址 3加上Allow
Arbitrary Loads 并设置为YES

相关文章