您的位置:首页 > 其它

多线程

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;

});

});
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: