iOS-Senior10-多线程(子线程创建)

1.多线程概述

程序:由源代码生成的可执行应用。(eg:QQ.app)

进程:一个正在运行的程序可以看做一个进程。(eg:正在运行的QQ就是一个进程),进程用用独立运行所需的全部资源。

线程:程序中独立运行的代码段。(eg:接收QQ消息的代码)

一个进程是由一或多个线程组成。进程只负责资源的调度和分配,线程才是程序真正的执行单元,负责代码的执行。

1.1单线程

每个正在运行的程序(即进程),至少包含一个线程,这个线程就叫主线程。

主线程在程序启动时被创建,用于执行main函数。

只有一个主线程的程序,称为单线程程序。

在单线程程序中,主线程负责执行程序的所有代码(UI展现以及刷新,网络请求,本地存储等等)。这些代码只能顺序执行,无法并发执行。

1.2多线程

拥有多个线程的程序,称作多线程程序。

iOS中允许用户自己开辟新的线程,相对于主线程来讲,这些线程,称作子线程。

可以根据需要开辟若干子线程。

子线程和主线程都是独立的运行单元,各自执行互不影响,因此能够并发执行。

1.3单线程和多线程的区别

单线程程序:只有一个线程,即主线程,代码顺序执行,容易出现代码阻塞(页面假死)。

多线程程序:有多个线程,线程间独立运行,能有效的避免代码阻塞,并且提高程序的运行性能。

注意:iOS中关于UI的添加和刷新必须在主线程中操作。

2.iOS平台下的多线程

2.1NSThread

方法:

//初始化一个子线程,但需要手动开启

- (id) initWithTarget : (id) target selector : (SEL)selector object :(id)argument

//初始化一个子线程,并自动开启

+ (void) detachNewThreadSelector : (SEL) aSelector toTarget : (id) aTarget withObject :(id) anArgument

//开启子线程

start   [operation start]

//取消当前子线程

cancel [operation cancel]

源代码:

//手动开辟子线程

NSThread *thread = [[NSThread alloc] initWithTarget : self selector:@selector(sayHi) object:nil];

[thread start];

//使用NSThread和NSObject实现的开辟线程,系统会自动释放,关不关都行

[thread cancel]; 没有真正取消,而是给线程发送一个信号,通过这个信号进行取消的

[thread exit];  直接将线程退出

//自动开启子线程

[NSThread detachNewThreadSelector:@selector(sayHi) toTarget:self withObject:nil];

self.view.backgroundColor = [UIColor redColor] ;

2.2NSObject

//使用performSelectorInBackground开辟子线程

[self performSelectorInBackground :@selector(sayHi) withObject:@"test"];

//在子线程调用的方法里返回主线程,在调用另一个方法

[self performSelectoraOnMainThread:@selector(mainThreadChangeColor) withObject :nil waitUntilDone: YES];

- (void)mainThreadChangeColor {

self.view.backgroudColor = [UIColor magentaColor];

}

方法:

获取当前线程:[NSThread currentThread]

获取主线程   :[NSThread mainThread]

线程休眠2秒 :[NSThread sleepForTimeInterval:2]

注意:

1.每个线程都维护这与自己对应的NSAutoreleasePool对象,将其放在线程栈的栈顶。当线程结束时,会清空自动释放池。

2.为保证对象的及时释放,在多线程方法中需要添加自动释放池。

3.在应用程序打开的时候,系统会自动为主线程创建一个自动释放池。

4.我们手动创建的子线程需要我们手动添加自动释放池。

4.NSOperation和NSOperationQueue

NSOperation类,在NVC中属于M,是用来封装单个任务相关的代码和数据的抽象类。

因为它是抽象的,不能够直接使用这个类,而是使用子类(NSInvocation,NSBlockOperation)来执行实际任务。

NSOperation(含子类),只是一个操作,本身无主线程,子线程之分,可在任意线程中使用。通常与NSOperationQueue结合使用。

//NSInvocationOperation:封装了执行操作的target和要执行的action

//NSBlockOperation:封装了需要执行的代码

//NSOperation不能直接进行多线程的创建,需要借助:NSOperationQueue

//在单独使用NSOperation的子类去创建线程的时候,一定要启动才行;

//在使用NSOperation的子类去创建线程的时候,实际上线程没有真正意义上的创建

源程序:

NSInvocationOperation *operation = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(test) object:nil];

NSBlockOperation *blockOperation = [NSBlockOperation blockOperationWithBlock:^{

NSLog(@"我是block");

NSLog(@"+++++%@",[NSThread currentThread]);

NSLog(@"*******%@",[NSThread mainThread]);

}];

- (void)test {

NSLog(@"?");

NSLog(@"currentThread == %@",[NSThread currentThread]);

NSLog(@"mainThread ==  %@",[NSThread mainThread]);

}

//借助队列,创建子线程

NSOperationQueue *queue = [[NSOperationQueue alloc] init];

[queue addOperation:operation];

[queue addOperation:blockOperation]; //有addOperation的时候,就不可以用start,否则会造成崩溃

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {

//创建队列的对象

NSOperationQueue *queue = [[NSOperationQueue alloc] init];

//最大的并发数量值

//当值设置为1的时候,可以叫做串行(单线程)顺序执行

queue.maxConcurrentOperationCount = 2;

//当值设置大于1的时候,叫做并行:多条通道同时进行各自的任务

for (int i = 0; i < 10; i++) {

//创建10个线程

NSBlockOperation *blockOperation = [NSBlockOperation blockOperationWithBlock:^{

NSLog(@"currentThread == %@,mainThread == %@,%d",[NSThread currentThread],[NSThread mainThread],i);

}];

[queue addOperation:blockOperation];

}

}

5.GCD(Grand Central Dispatch)使用

简介:GCD是Apple开发的一种多核编程技术。主要用于优化应用程序以支持多核处理器以及其他对称多处理系统。

GCD提供函数实现多线程开发,性能更高,功能也更强大。

它首次发布在Mac OS X 10.6,iOS4及以上也可以用。

任务:具有一定功能的代码段。一般是一个block或者函数。

分发队列:GCD以队列的方式进行工作,FIFO(先进先出)

GCD会根据分发队列的类型,创建合适数量的线程执行队列中的任务。

GCD中两种队列:

1.SerialQueue:一次只执行一个任务。Serial queue通常用于通常用于同步访问特定的资源或数据。当你创建多个Serial queue时,虽然他们各自是同步执行的,但Serial queue与Serial queue之间是并发执行的。

2.Concurrent:可以并发地执行多个任务,但是遵守FIFO

#pragma mark - 使用GCD去创建一个串行队列

//第一种:系统提供的创建串行队列的方法

dispatch_queue_t queue = dispatch_get_main_queue();

//在真正的开发中如果需要创建串行队列,比较习惯用这种

//第二种:自己去创建

dispatch_queue_t = dispatch_queue_create(DISPATCH_QUEUE_SERIAL,0);

#pragma mark - 使用GCD去创建并行队列

//第一种:系统的方式

//参数1:优先级(有4个,没有明显的区别)

dispatch_queue_t queue = dispatch_get_globel_queue(DISPATCH_QUEUE_PRIORITY);

//第二种:自己定义的方式(参数和串行不一样)

//参数1:表示创建队列的名字

//参数2:系统提供的宏

//创建队列

dispatch_queue_t queue = dispatch_queue_create("myQueue",DISPATCH_QUEUE_CONCURRENT);

//创建任务

dispatch_async(queue,^{

NSLog(@"current == %@",[NSThread currentThread]);

NSLog(@"main == %@",[NSThread MainThread]);

NSLog(@"我是任务一,子进程一");

});

dispatch_async(queue,^{

NSLog(@"current == %@",[NSThread currentThread]);

NSLog(@"main == %@",[NSThread MainThread]);

NSLog(@"我是任务二,子进程二");

});

dispatch_async(queue,^{

NSLog(@"current == %@",[NSThread currentThread]);

NSLog(@"main == %@",[NSThread MainThread]);

NSLog(@"我是任务三,子进程三");

});

#pragma mark - 几秒之后去做每一件事

dispatch_after(dispatch_time(DISPATCH_TIME_NOW,(int64_t)(3.0 * NSEC_PER_SEC)),dispatch_get_main_queue(),^{

NSLog(@"3.0秒的时候");

}

);

#pragma mark - 重复向一个队列中添加多个任务

dispatch_queue_t queue = dispatch_queue_create(0,DISPATH_QUEUE_CONCURRENT);

dispatch_apply(100,queue,^(size_t index)) {

NSLog(@"index = %zu",index);

}

#pragma mark - 分组

//创建一个分组

dispatch_group_t group = dispatch_group_create();

//创建一个并行队列

dispatch_queue_t queue = dispatch_queue_create(0,DISPATCH_QUEUE_CONCURRENT);

//创建任务1

dispatch_group_asunc(group,queue,^{

NSLog(@"我是任务1");

});

//创建任务2

dispatch_group_asunc(group,queue,^{

NSLog(@"我是任务2");

});

//创建任务3

dispatch_group_asunc(group,queue,^{

NSLog(@"我是任务3");

});

//用于监听所有任务的执行情况的,所以此功能代码必须放在所有任务之后进行书写的

dispatch_group_notify(group,queue,^{

NSLog(@"我是监听的,最后执行");

});

#pragma mark - 并发中的串行(披着羊皮的狼)

//创建的串行队列

dispatch_queue_t queue = dispatch_queue_create(0,DISPATH_QUEUE_CONCURRENT);

dispatch_async(queue,^{

NSLog(@"任务1");

});

dispatch_async(queue,^{

NSLog(@"任务2");

});

dispatch_async(queue,^{

NSLog(@"任务3");

});

#pragma mark - loadData

//1.url

NSURL *url = [NSURL URLWithString:@"http://www.baidu.com"];

//2.session

NSURLSession *session = [NSURLSession sharedSession];

//3.task

NSURLSessionDataTask *task = [session dataTaskWithURL:url completionHandler:^(NSData *_NUllabel data,NSURLResponse *_Nullabel response,NSError *_Nullable error){

if(error == nil){

//处理数据

//回到主线程刷新UI

dispatch_async(dispatch_get_main_queue(),^{

//自己灵活的写点东西吧!!!

})

}

}];

时间: 2024-10-06 07:42:00

iOS-Senior10-多线程(子线程创建)的相关文章

iOS开发多线程篇—线程的状态

iOS开发多线程篇—线程的状态 一.简单介绍 线程的创建: self.thread=[[NSThread alloc]initWithTarget:self selector:@selector(test) object:nil]; 说明:创建线程有多种方式,这里不做过多的介绍. 线程的开启: [self.thread start]; 线程的运行和阻塞: (1)设置线程阻塞1,阻塞2秒 [NSThread sleepForTimeInterval:2.0]; (2)第二种设置线程阻塞2,以当前时

iOS开发多线程篇—线程间的通信

iOS开发多线程篇—线程间的通信 一.简单说明 线程间通信:在1个进程中,线程往往不是孤立存在的,多个线程之间需要经常进行通信 线程间通信的体现 1个线程传递数据给另1个线程 在1个线程中执行完特定任务后,转到另1个线程继续执行任务 线程间通信常用方法 - (void)performSelectorOnMainThread:(SEL)aSelector withObject:(id)arg waitUntilDone:(BOOL)wait; - (void)performSelector:(SE

iOS开发多线程篇—线程的状态 - 文顶顶

原文  http://www.cnblogs.com/wendingding/p/3807184.html iOS开发多线程篇-线程的状态 一.简单介绍 线程的 创建 : self.thread=[[NSThread alloc]initWithTarget:self selector:@selector(test) object:nil]; 说明:创建线程有多种方式,这里不做过多的介绍. 线程的 开启 : [self.thread start]; 线程的 运行 和 阻塞 : (1)设置线程阻塞

iOS开发多线程篇—线程间的通信(转)

这里转载 给自己一个备份 一.简单说明 线程间通信:在1个进程中,线程往往不是孤立存在的,多个线程之间需要经常进行通信 线程间通信的体现 1个线程传递数据给另1个线程 在1个线程中执行完特定任务后,转到另1个线程继续执行任务 线程间通信常用方法 - (void)performSelectorOnMainThread:(SEL)aSelector withObject:(id)arg waitUntilDone:(BOOL)wait; - (void)performSelector:(SEL)aS

iOS开发多线程篇—线程安全 - 文顶顶

原文  http://www.cnblogs.com/wendingding/p/3805841.html iOS开发多线程篇—线程安全 一.多线程的安全隐患 资源共享 1 块资源可能会被多个线程共享,也就是多个线程可能会访问同一块资源 比如多个线程访问同一个对象.同一个变量.同一个文件 当多个线程访问同一块资源时,很容易引发数据错乱和数据安全问题 示例一: 示例二: 问题代码: 1 // 2 // YYViewController.m 3 // 05-线程安全 4 // 5 // Create

iOS开发多线程篇—线程安全

iOS开发多线程篇—线程安全 一.多线程的安全隐患 资源共享 1块资源可能会被多个线程共享,也就是多个线程可能会访问同一块资源 比如多个线程访问同一个对象.同一个变量.同一个文件 当多个线程访问同一块资源时,很容易引发数据错乱和数据安全问题 示例一: 示例二: 问题代码: 1 // 2 // YYViewController.m 3 // 05-线程安全 4 // 5 // Created by apple on 14-6-23. 6 // Copyright (c) 2014年 itcase.

Java基础加强之多线程篇(线程创建与终止、互斥、通信、本地变量)

线程创建与终止 线程创建 Thread类与Runnable接口的关系 public interface Runnable { public abstract void run(); } public class Thread implements Runnable { /* What will be run. */ private Runnable target; ...... /** * Causes this thread to begin execution; the Java Virtu

iOS中多线程_05_线程间通信NSThread/GCD

1.什么叫做线程间通信 在1个进程中,线程往往不是孤立存在的,多个线程之间需要经常进行通信 2.线程间通信的体现 1个线程传递数据给另1个线程 在1个线程中执行完特定任务后,转到另1个线程继续执行任务 3.线程间通信示例 UIImageView下载图片这个例子, 主线程中开启一个子线程去下载图片, 当图片下载完成之后再回到主线程中更新显示图片, 这样的一个过程就是线程间通信的一个过程. 4.NSThread线程间通信常用方法 // 第一种- (void)performSelectorOnMain

iOS开发多线程篇---线程间的通信

线程间通信的表现: 1个线程传递数据给另1个线程 在1个线程中执行完特定任务后,转到另1个线程继续执行任务 下面是一个下载图片的例子: @interface BTThreadViewController () {     UIImageView *imagev; } @end - (void)viewDidLoad {     [super viewDidLoad];          imagev = [[UIImageView alloc] initWithFrame:CGRectMake(