什么是多线程?
一句话,对功能的实现的流程,一个流程就是一个线程。在一个程序运行时至少有一个线程在运行,这个线程就是主线程。单线程下,只有当前的功能执行完毕,才执行下一个功能,给用户最直观的感受就是程序静止不动了。多线程就能解决这样的问题,他的原理是,吧功能分化称若干某块,然后有系统为其分配若干个线程,这些线程之间互不干扰,并行运作。提高了用户的体验感受,更加合理的发挥了系统的资源利用率。可是,这样加大了我们对多个线程之间合理安排的难度,比如说多线程的传值问题,相应处理。这就是线程管理所属的范畴。
只有一个线程的程序是单线程程序,主线程负责程序的所有代码(UI的展示、刷新、网络请求、本地存储)。这些代码只能顺序执行,无法并发执行。主线程在程序启动的时被创建,用于执行Main 函数。
拥有多个线程的程序被称为多线程。IOS允许用户自己开辟新的线程,相对于主线程来说这些线程被称为是子线程。主线程和子线程是独立的
调整程序的时候,最好不要去破坏原有运行正常的代码。
并行就是多个指令在多个处理器上执行,并发就是同一时刻只有一条指令在执行,但是多个进程指令被快速轮换,使得在宏观上似乎是同时执行的效果。
单CPU多线程仅仅解决了流畅的问题,并没有真正的解决线程之间的阻塞等待,但是多线程就解决此问题,是并行的计算的。
最形象的比喻来阐明上述的概念:
你吃饭吃到一半,电话来了,你一直到吃完了以后才去接,这就说明你不支持并发也不支持并行。
你吃饭吃到一半,电话来了,你停了下来接了电话,接完后继续吃饭,这说明你支持并发。
你吃饭吃到一半,电话来了,你一边打电话一边吃饭,这说明你支持并行。
并发的关键是你有处理多个任务的能力,不一定要同时。
并行的关键是你有同时处理多个任务的能力。
所以我认为它们最关键的点就是:是否是『同时』。
理解并行于并发的区别
线程的创建,并执行线程:
- (void)viewDidLoad { [super viewDidLoad]; for(int i = 0 ; i < 100 ; i++) { NSLog(@"===%@===%d" , [NSThread currentThread].name , i); if(i == 20) { // 创建线程对象 NSThread *thread = [[NSThread alloc]initWithTarget:self selector:@selector(run) object:nil]; // 启动新线程 [thread start]; // 创建并启动新线程 [NSThread detachNewThreadSelector:@selector(run) toTarget:self withObject:nil]; } } } - (void)run { for(int i = 0 ; i < 100 ; i++) { NSLog(@"-----%@----%d" , [NSThread currentThread].name, i); } }
线程的状态:
线程被创建启动后,他并不是一启动就进入执行状态、也不是一直处于 执行状态。一个启动的线程会处于待命状态,不可能一直霸占CPU资源,他会一直在待命——执行——待命——执行这样的循环着切换,至于何时切换则取决于系统的资源调度。只有被调度多线程才会处于执行状态。当线程对象启动 star 方法的时候,线程就处于待命状态,但是未必立即执行,要想提高执行速度中,让其立即执行,可以设定当主线程休眠0.001秒就是1毫秒的时候,立即运行子线程,使用方法为 NSThread.sleepForTimeINterval(0.001),这样主线程会在休眠1毫秒后立即执行子线程,这1毫秒内CPU在处理其他的事物并未闲置:
NSThread* thread; - (void)viewDidLoad { [super viewDidLoad]; // 创建新线程对象 thread = [[NSThread alloc] initWithTarget:self selector:@selector(run) object:nil]; // 启动新线程 [thread start]; } - (void)run { for(int i = 0 ; i < 100 ; i++) { if([NSThread currentThread].isCancelled) { // 终止当前正在执行的线程 [NSThread exit]; } NSLog(@"-----%@----%d" , [NSThread currentThread].name, i); // 每执行一次,线程暂停0.5秒 [NSThread sleepForTimeInterval:0.5]; } } - (IBAction)cancelThread:(id)sender { // 取消thread线程,调用该方法后,thread的isCancelled方法将会返回NO [thread cancel]; }
使用多线程去下载图片如下:
- (IBAction)showImage:(id)sender { NSString* url = @"https://ss0.bdstatic.com/5aV1bjqh_Q23odCf/static/superman/img/logo/bd_logo1_31bdc765.png"; // 创建新线程对象 NSThread *thread = [[NSThread alloc]initWithTarget:self selector:@selector(downloadImageFromURL:) object:url]; // 启动线程 [thread start]; } // 定义一个方法作为线程执行体。 -(void)downloadImageFromURL:(NSString *) url { // 从网络获取数据 NSData *data = [[NSData alloc] initWithContentsOfURL:[NSURL URLWithString:url]]; // 将网络数据初始化为UIImage对象 UIImage *image = [[UIImage alloc]initWithData:data]; if(image != nil) { // 在主线程中执行updateUI:方法 [self performSelectorOnMainThread:@selector(updateUI:) withObject:image waitUntilDone:YES]; // ① } else { NSLog(@"---下载图片出现错误---"); } } -(void)updateUI:(UIImage*) image { self.iv.image = image; }
取消线程如下:
NSThread* thread; - (void)viewDidLoad { [super viewDidLoad]; // 创建新线程对象 thread = [[NSThread alloc] initWithTarget:self selector:@selector(run) object:nil]; // 启动新线程 [thread start]; } - (void)run { for(int i = 0 ; i < 100 ; i++) { if([NSThread currentThread].isCancelled) { // 终止当前正在执行的线程 [NSThread exit]; } NSLog(@"-----%@----%d" , [NSThread currentThread].name, i); // 每执行一次,线程暂停0.5秒 [NSThread sleepForTimeInterval:0.5]; } } - (IBAction)cancelThread:(id)sender { // 取消thread线程,调用该方法后,thread的isCancelled方法将会返回NO [thread cancel]; }
待续。。。。