1⃣️多线程与单线程
-单线程:在应用程序启动的时候回自动创建一个线程,该线程为主线程。只有一个主线程的应用程序为单线程应用程序。在主线程的代码会顺序执行。
-单线程程序的问题: 在程序运行的过程中难免会需要请求数据、解析数据等等很多很耗时的任务。这时如果把所有的任务都放在主线程中执行会造成程序的假死现象,用户交互性不好。
-为了提高用户的交互性,可以采用多线程。
-多线程:即程序中不仅仅有一个主线程,在存在其他线程,除了主线程意外的其他线程都成为子线程。这些子线程主要用来进行一些复杂的工作。
==》问题:如何开辟子线程?
-使用多线程注意事项:不管开辟多少个子线程,最终UI界面的刷新和展示(即所有对UI的操作)都需要回到主线程中执行。
==》问题:如何从子线程回到主线程?
-使用多线程的优缺点:
>.优点:可以防止线程阻塞,提高用户交互性。
>.缺点:1.在开辟子线程的时候需要耗费一定的资源。
2.不管开辟了多少个子线程最终都要回到主线程,这时也需要耗费CPU性能
3.子线程开辟过多会造成代码可读性差(基本上都是block惹的祸, 关键谁愿意看别人代码?)
-下面就根据以上两个问题展开多线程编程的笔记,
2⃣️如何开辟子线程?
-首先,我们要知道:在main.m文件中,系统已经对主线程进行了内存管理。添加了自动释放池。然而并没有对子线程进行内存管理,所以就需要程序员在写子线程方法的时候添加自动释放池来释放一些创建的对象。
问题一:如何开辟子线程?
第一种方式
NSThread
:方法一、(
在使用下列方法时需注意该方法不会自动开辟子线程执行方法,需要手动调用start开启)
NSThread *thread1 = [[NSThread alloc] initWithTarget:self selector:@selector(calculate) object:nil];
方法二、(
该方法开辟子线程会自动执行方法,不需要手动调用start开启)
[
NSThread
detachNewThreadSelector
:
@selector
(calculate:)
toTarget
:
self
withObject
:
self
.
myTF
.
text
]
第二种方式
NSObject:(
凡是继承自NSObject的类都可以使用该方法,该方法调用几次就会开辟几个子线程
)
[
self
performSelectorInBackground
:
@selector
(downlodMyImage:)
withObject
:url];
第三种方式
NSOperationQueue:(
操作队列,用来管理一组操作(NSOperation);注意事项:NSOperationQueue开辟的线程的个数是由系统决定的,不是有操作的个数决定的)
首先创建操作:
创建两个
NSOperation(NSBlockOperation\NSInvocationOperation)
NSBlockOperation *blockOp = [ NSBlockOperation blockOperationWithBlock :^{
NSLog ( @"blockThread:%@" ,[ NSThread currentThread ]);
}];
NSBlockOperation *blockOp = [ NSBlockOperation blockOperationWithBlock :^{
NSLog ( @"blockThread:%@" ,[ NSThread currentThread ]);
}];
NSInvocationOperation *invocationOp = [[NSInvocationOperationalloc]initWithTarget:selfselector:@selector(calculate:)object:@"2453"];
然后用
NSOperationQueue来管理一组操作:
NSOperationQueue *queue = [[NSOperationQueuealloc]init];
[queue
addOperations
:
@[
blockOp,invocationOp
]
waitUntilFinished
:
NO
];
第四种方式
GCD
:(
GCD的核心是分发队列:两种形式:1、串行队列:一次只能执行一个任务,如果有多个串行队列,每个队列中的任务都是同步执行的,但是队列之间可以并发执行2、并行队列:并发的执行多个任务,但是FIFO(其实只支持先进,并不一定先出。))
形式1、串行队列:
dispatch_queue_t
queue =
dispatch_queue_create
(
"com.fy.queue1"
,
DISPATCH_QUEUE_SERIAL
);
dispatch_async (queue, ^{
NSLog ( @"thread:%@" ,[ NSThread currentThread ]);
dispatch_async (queue, ^{
NSLog ( @"thread:%@" ,[ NSThread currentThread ]);
});
形式2、并行队列:
dispatch_async
(
dispatch_get_global_queue
(
0
,
0
), ^{
NSLog ( @"global:%@" ,[ NSThread currentThread ]);
NSLog ( @"global:%@" ,[ NSThread currentThread ]);
});
问题二:如何从子线程回到主线程?
方法
1
:
NSObject
对应的方法:
performSelectorOnMainThread
方法2(GCD)、dispatch_async(dispatch_get_main_queue(), ^{ });