多线程
2016-01-26 11:17
232 查看
//
多线程
//
单线程:
在应用程序启动的时候,会自动创建一个线程。该线程为主线程。只有一个主线程的应用程序为单线程应用程序。在主线程的代码会顺序执行。
//
单线程程序的问题:在程序运行的过程中难免会需要请求数据、解析数据等等很多耗时的任务。这时如果把所有的任务都放在主线程中执行会造成程序的假死现象,用户交互不好。
//
为了提高用户的交互性,可以采用多线程。
//
多线程:即程序中不仅仅有一个主线程。这些子线程主要用来进行一些复杂的工作。
//
使用多线程注意事项:不管开辟的多少个子线程,最终UI界面的刷新和展示(即所有对UI的操作)都需要回到主线程中执行。
==>>
问题:如何从子线程回到主线程?
//
使用多线程的优缺点:
//
优点:可以防止主线程阻塞,提用户交互性。
//
缺点: 1.在开辟子线程的时候需要耗费一定的资源。
// 2.不管开辟了多少个子线程最终要回到主线程,这时也需要耗
费CPU性能。
// 3.子线程开辟过多少会造成代码可读性比较差。
//
问题一:如何从子线程回到主线程:
// 1.NSObject对应的方法:performSelectorOnMainThread
// 2.dispatch_async(dispatch_get_main_queue(), ^{});
/********************第一种方式NSThread********************/
//
获取当前的线程(thread)
NSLog(@"mainThread:%@", [NSThread
currentThread]);
// initWithTarget:selector:object:参数含义如下:
// 1.目标
// 2.方法名
// 3.方法对于的参数
//
在使用下列方法时需要注意该方法不会自动开辟子线程执行方法,需要手动调用start开启。
(开辟子线程)
// NSThread *thread1 = [[NSThread alloc] initWithTarget:self selector:@selector(calculate:) object:self.NumberTF.text];
// //
开启
// [thread1 start];
//
这个方法使用会立即跳到子线程,
不需要手动Start
[NSThread
detachNewThreadSelector:@selector(calculate:)
toTarget:self
withObject:self.NumberTF.text];
//
在子线程里加载图片,然后回到主线程显示图片
/***************方式二使用NSObject*****************/
NSURL
*url = [NSURL
URLWithString:kURL];
#pragma mark -
该方法是NSObject的方法,凡是继承NSObject的类都可以使用该方法。该方法调用几次就会开辟几个子线程。==>
问题:如果不同线程争夺同一个资源,咋办?
// @synchronized(<#token#>) { //
线程锁方法一
// <#statements#>
// }
[self
performSelectorInBackground:@selector(downloadMyImage:)
withObject:url];
//
开启子线程
/************方式三
使用NSOperationQueue*************/
// NSOperationQueue:操作队列。用来管理一组操作(NSOperation)。
//
注意事项:NSOperationQueue开辟线程的个数是由系统决定的。不是由操作的个数决定的。(⭐️⭐️⭐️⭐️⭐️)
==>面试题!!!
//
创建两个NSOperation(NSBlockOperation\ NSInvocation)
NSBlockOperation
*blockOp = [NSBlockOperation
blockOperationWithBlock:^{
NSLog(@"blockThread:%@", [NSThread
currentThread]);
}];
NSInvocationOperation
*invocationOp = [[NSInvocationOperation
alloc]
initWithTarget:self
selector:@selector(calculate:)
object:@"50"];
NSOperationQueue
*queue = [[NSOperationQueue
alloc]
init];
#pragma mark -
下列方法中参数的含义:
// 1.操作对应的数组
// 2.BOOL:如果给的是YES,那么会阻塞当前线程,直到操作队列里面所有的操作被执行完,当前线程才不会被阻塞。
//
如果给的是NO,那么不会阻塞当前线程。
//
可能会产生的问题:如果给的是YES,而且卡死的是主线程。那么在操作中如果需要对UI进行操作需要返回到主线程中去执行代码。这时程序就会出现死锁(一直出不来,按键也一直不能再次点击)。
//
设置最大并发数为1.(当前在操作队列中正在运行的任务只有一个。与线程个数无关。)
//
如果设置最大并发数为1,那么可以实现线程同步。
//
线程同步:只有当一个线程中的任务执行完毕之后,才能执行另外一个线程的任务。
queue.maxConcurrentOperationCount
=
1;
[queue
addOperations:@[blockOp, invocationOp]
waitUntilFinished:NO];
/*************************方式四
GCD************************/
// GCD的核心是分发队列。
//
分发队列有两种形式:
//
串行队列:
一次只能执行一个任务。如果有多个串行队列那么每个队列中的任务都是同步执行的,但是队列之间可以并发执行(互不干扰)。
//
并行队列:
并发的执行多个任务。但是FIFO.(只支持先进,并不一定先出。)
- (IBAction)serialQueue:(id)sender {
//
串行队列有两种形式:
// 1.系统提供的:dispatch_async(dispatch_get_main_queue:
主队列
==>> 在主线程中。
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"下载图片:%@",
[NSThread
currentThread]);
});
// 2.自己创建的(自己创建的会再子线程)
dispatch_queue_t
queue =
dispatch_queue_create("com.fy.queue1",
DISPATCH_QUEUE_SERIAL);
dispatch_async(queue, ^{
NSLog(@"thread:%@", [NSThread
currentThread]);
//子线程中
});
//
串行是顺序执行
dispatch_async(queue, ^{
NSLog(@"小米出生了");
});
dispatch_async(queue, ^{
NSLog(@"小米上学了");
});
dispatch_async(queue, ^{
NSLog(@"小米结婚了");
});
dispatch_async(queue, ^{
NSLog(@"小米有宝宝了");
});
}
- (IBAction)concurrentQueue:(id)sender {
//
并行队列有两种:
// 1.系统提供的
(也是子线程)
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,
0), ^{
NSLog(@"======:%@", [NSThread
currentThread]);
});
// 2.自己创建的
dispatch_queue_t
concurrentQueue =
dispatch_queue_create("com.fy.concurrentQueue",
DISPATCH_QUEUE_CONCURRENT);
dispatch_async(concurrentQueue, ^{
NSLog(@"thread:%@", [NSThread
currentThread]);
//
子线程中
});
//
并行队列与顺序没有关系,是无序的
dispatch_async(concurrentQueue, ^{
NSLog(@"小米出生了");
});
dispatch_async(concurrentQueue, ^{
NSLog(@"小米上学了");
});
dispatch_async(concurrentQueue, ^{
NSLog(@"小米结婚了");
});
dispatch_async(concurrentQueue, ^{
NSLog(@"小米有宝宝了");
});
}
//
使用GCD
- (IBAction)useGCD:(id)sender {
dispatch_queue_t
myQueue =
dispatch_queue_create("com.fy.myQueue",
DISPATCH_QUEUE_SERIAL);
dispatch_async(myQueue, ^{
UIImage
*image = [UIImage
imageWithData:[NSData
dataWithContentsOfURL:[NSURL
URLWithString:kImage]]];
dispatch_async(dispatch_get_main_queue(), ^{
self.imageView.image
= image;
});
});
}
多线程
//
单线程:
在应用程序启动的时候,会自动创建一个线程。该线程为主线程。只有一个主线程的应用程序为单线程应用程序。在主线程的代码会顺序执行。
//
单线程程序的问题:在程序运行的过程中难免会需要请求数据、解析数据等等很多耗时的任务。这时如果把所有的任务都放在主线程中执行会造成程序的假死现象,用户交互不好。
//
为了提高用户的交互性,可以采用多线程。
//
多线程:即程序中不仅仅有一个主线程。这些子线程主要用来进行一些复杂的工作。
//
使用多线程注意事项:不管开辟的多少个子线程,最终UI界面的刷新和展示(即所有对UI的操作)都需要回到主线程中执行。
==>>
问题:如何从子线程回到主线程?
//
使用多线程的优缺点:
//
优点:可以防止主线程阻塞,提用户交互性。
//
缺点: 1.在开辟子线程的时候需要耗费一定的资源。
// 2.不管开辟了多少个子线程最终要回到主线程,这时也需要耗
费CPU性能。
// 3.子线程开辟过多少会造成代码可读性比较差。
//
问题一:如何从子线程回到主线程:
// 1.NSObject对应的方法:performSelectorOnMainThread
// 2.dispatch_async(dispatch_get_main_queue(), ^{});
/********************第一种方式NSThread********************/
//
获取当前的线程(thread)
NSLog(@"mainThread:%@", [NSThread
currentThread]);
// initWithTarget:selector:object:参数含义如下:
// 1.目标
// 2.方法名
// 3.方法对于的参数
//
在使用下列方法时需要注意该方法不会自动开辟子线程执行方法,需要手动调用start开启。
(开辟子线程)
// NSThread *thread1 = [[NSThread alloc] initWithTarget:self selector:@selector(calculate:) object:self.NumberTF.text];
// //
开启
// [thread1 start];
//
这个方法使用会立即跳到子线程,
不需要手动Start
[NSThread
detachNewThreadSelector:@selector(calculate:)
toTarget:self
withObject:self.NumberTF.text];
//
在子线程里加载图片,然后回到主线程显示图片
/***************方式二使用NSObject*****************/
NSURL
*url = [NSURL
URLWithString:kURL];
#pragma mark -
该方法是NSObject的方法,凡是继承NSObject的类都可以使用该方法。该方法调用几次就会开辟几个子线程。==>
问题:如果不同线程争夺同一个资源,咋办?
// @synchronized(<#token#>) { //
线程锁方法一
// <#statements#>
// }
[self
performSelectorInBackground:@selector(downloadMyImage:)
withObject:url];
//
开启子线程
/************方式三
使用NSOperationQueue*************/
// NSOperationQueue:操作队列。用来管理一组操作(NSOperation)。
//
注意事项:NSOperationQueue开辟线程的个数是由系统决定的。不是由操作的个数决定的。(⭐️⭐️⭐️⭐️⭐️)
==>面试题!!!
//
创建两个NSOperation(NSBlockOperation\ NSInvocation)
NSBlockOperation
*blockOp = [NSBlockOperation
blockOperationWithBlock:^{
NSLog(@"blockThread:%@", [NSThread
currentThread]);
}];
NSInvocationOperation
*invocationOp = [[NSInvocationOperation
alloc]
initWithTarget:self
selector:@selector(calculate:)
object:@"50"];
NSOperationQueue
*queue = [[NSOperationQueue
alloc]
init];
#pragma mark -
下列方法中参数的含义:
// 1.操作对应的数组
// 2.BOOL:如果给的是YES,那么会阻塞当前线程,直到操作队列里面所有的操作被执行完,当前线程才不会被阻塞。
//
如果给的是NO,那么不会阻塞当前线程。
//
可能会产生的问题:如果给的是YES,而且卡死的是主线程。那么在操作中如果需要对UI进行操作需要返回到主线程中去执行代码。这时程序就会出现死锁(一直出不来,按键也一直不能再次点击)。
//
设置最大并发数为1.(当前在操作队列中正在运行的任务只有一个。与线程个数无关。)
//
如果设置最大并发数为1,那么可以实现线程同步。
//
线程同步:只有当一个线程中的任务执行完毕之后,才能执行另外一个线程的任务。
queue.maxConcurrentOperationCount
=
1;
[queue
addOperations:@[blockOp, invocationOp]
waitUntilFinished:NO];
/*************************方式四
GCD************************/
// GCD的核心是分发队列。
//
分发队列有两种形式:
//
串行队列:
一次只能执行一个任务。如果有多个串行队列那么每个队列中的任务都是同步执行的,但是队列之间可以并发执行(互不干扰)。
//
并行队列:
并发的执行多个任务。但是FIFO.(只支持先进,并不一定先出。)
- (IBAction)serialQueue:(id)sender {
//
串行队列有两种形式:
// 1.系统提供的:dispatch_async(dispatch_get_main_queue:
主队列
==>> 在主线程中。
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"下载图片:%@",
[NSThread
currentThread]);
});
// 2.自己创建的(自己创建的会再子线程)
dispatch_queue_t
queue =
dispatch_queue_create("com.fy.queue1",
DISPATCH_QUEUE_SERIAL);
dispatch_async(queue, ^{
NSLog(@"thread:%@", [NSThread
currentThread]);
//子线程中
});
//
串行是顺序执行
dispatch_async(queue, ^{
NSLog(@"小米出生了");
});
dispatch_async(queue, ^{
NSLog(@"小米上学了");
});
dispatch_async(queue, ^{
NSLog(@"小米结婚了");
});
dispatch_async(queue, ^{
NSLog(@"小米有宝宝了");
});
}
- (IBAction)concurrentQueue:(id)sender {
//
并行队列有两种:
// 1.系统提供的
(也是子线程)
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,
0), ^{
NSLog(@"======:%@", [NSThread
currentThread]);
});
// 2.自己创建的
dispatch_queue_t
concurrentQueue =
dispatch_queue_create("com.fy.concurrentQueue",
DISPATCH_QUEUE_CONCURRENT);
dispatch_async(concurrentQueue, ^{
NSLog(@"thread:%@", [NSThread
currentThread]);
//
子线程中
});
//
并行队列与顺序没有关系,是无序的
dispatch_async(concurrentQueue, ^{
NSLog(@"小米出生了");
});
dispatch_async(concurrentQueue, ^{
NSLog(@"小米上学了");
});
dispatch_async(concurrentQueue, ^{
NSLog(@"小米结婚了");
});
dispatch_async(concurrentQueue, ^{
NSLog(@"小米有宝宝了");
});
}
//
使用GCD
- (IBAction)useGCD:(id)sender {
dispatch_queue_t
myQueue =
dispatch_queue_create("com.fy.myQueue",
DISPATCH_QUEUE_SERIAL);
dispatch_async(myQueue, ^{
UIImage
*image = [UIImage
imageWithData:[NSData
dataWithContentsOfURL:[NSURL
URLWithString:kImage]]];
dispatch_async(dispatch_get_main_queue(), ^{
self.imageView.image
= image;
});
});
}
相关文章推荐
- AndroidStudio自动导入包
- 一小时搞定DIV+CSS布局-固定页面开度布局
- ibatis 到 MyBatis区别
- oracle脚本处理数据,还原后重新处理
- Python列表解析
- 去处HTML标签
- js中匿名函数的N种写法
- form 表单处理
- 基于JavaScript如何制作遮罩层对话框
- MQTT在Linux下的体验
- 自然语言处理中的Attention Model:是什么及为什么
- IOS开发中的几种设计模式介绍
- 数据解析
- 第8周项目分支程序设计
- TCP的三次握手和四次挥手
- tableview使用xib 创建cell
- 使用grub引导恢复linxu引导
- underscorejs-filter学习
- EasyUI datagrid 笔记
- Python RawSocket Syn