标签:执行 需要 ack load with 更新 objc 用户创建 在线
iOS在每个进程启动后都会创建一个主线程,更新UI要在主线程上
,所以也称为UI线程,是其他线程的父线程。
NSThreadhi轻量级的多线程开发,需要自己管理线程生命周期
/* 直接将操作添加到新线程中并执行,该方法无法拿到线程对象 */
+ (void)detachNewThreadSelector:(SEL)selector /* 方法名 */
toTarget:(id)target /* 调用对象 */
withObject:(id)argument; /* 参数 */
/* 创建线程对象,初始化线程任务,调用start方法启动线程 */
- (instancetype)initWithTarget:(id)target /* 调用对象 */
selector:(SEL)selector /* 方法名 */
object:(id)argument;/* 参数 */
/* 创建一个线程,初始化任务,创建线程并不会启动线程 */
NSThread *thread = [[NSThread alloc] initWithTarget:self
selector:@selector(loadImage)
object:nil];
[thread start];//启动线程
/* 直接将操作添加到新线程并启动线程 */
[NSThread detachNewThreadSelector:@selector(loadImage)
toTarget:self
withObject:nil];
- 每个线程的实际执行顺序并不一定按启动顺序执行
/* 让线程休眠 */
+ (void)sleepUntilDate:(NSDate *)date;/* 让当前执行线程休眠到某个时间 */
+ (void)sleepForTimeInterval:(NSTimeInterval)time;/* 让当前执行线程休眠固定多少秒 */
/* 终止线程 */
+ (void)exit;
/* 停止线程,注意在主线程中调用仅仅只是设置线程状态,不会立刻停止线程 */
- (void)cancel;
NSThread *thread = threads[i];
//判断线程是否完成,如果没有完成则设置为取消状态
//注意设置为取消状态仅仅是改变了线程状态而言,并不能立刻终止线程
if ( !thread.isFinished ) {
[thread cancel];
}
//线程休眠2秒
[NSThread sleepForTimeInterval:2.0];
我们知道了控制单个线程,怎么在线程之间进行通信呢?
/* 在后台执行一个操作,本质就是重新创建一个线程执行当前方法 */
- (void)performSelectorInBackground:(SEL)aSelector
withObject:(id)arg;
/* 在指定的线程上执行一个方法,需要用户创建一个线程对象 */
- (void)performSelector:(SEL)aSelector
onThread:(NSThread *)thr
withObject:(id)arg
waitUntilDone:(BOOL)wait;
/* 在主线程上执行一个方法 */
- (void)performSelectorOnMainThread:(SEL)aSelector
withObject:(id)arg
waitUntilDone:(BOOL)wait;
只要将NSOperation放入NSOperationQueue线程队列中,就会启动执行。
NSOperationQueue负责管理、执行所有的NSOperation,这样更加容易管理线程总数和控制线程之间的依赖。
//创建Invocation线程
NSInvocationOperation *invocationOperation =
[[NSInvocationOperation alloc] initWithTarget:self
selector:@selector(loadImage)
object:nil];
//注意如果直接调用start方法,则此操作会在主线程中调用
// [invocationOperation start];//一般不会这么操作,而是添加到NSOperationQueue中
//创建线程队列
NSOperationQueue *operationQueue = [[NSOperationQueue alloc] init];
operationQueue.maxConcurrentOperationCount = 5;//设置最大并发线程数
//注意添加到线程队列后,队列里的线程就会开始执行
[operationQueue addOperation:invocationOperation];
//创建Block线程
NSBlockOperation *blockOperation = [NSBlockOperation blockOperationWithBlock:^{
[self loadImage:[NSNumber numberWithInt:0]];
}];
//添加进线程队列
[operationQueue addOperation:blockOperation];
如果觉得添加NSBlockOperation线程麻烦,还有个简单的方法,是NSOperationQueue的对象方法:
// 快捷添加NSBlockOperation
[operationQueue addOperationWithBlock:^{
[self loadImage:[NSNumber numberWithInt:0]];
}];
我说过NSOperationQueue可以控制线程之间的依赖,这是怎么一回事呢?想象一种场景,加载多个图片,但我想最后一张图片一定要先加载,其他图片加载的前提就是最后一张图片要加载完成,这时候就可以使用依赖了。非常简单。
- (void)loadImageWithMultiThread{
int count = ROW_COUNT*COLUMN_COUNT;
//创建线程队列
NSOperationQueue *operationQueue = [[NSOperationQueue alloc]init];
operationQueue.maxConcurrentOperationCount = 5;//设置最大并发线程数
//创建加载最后一张图片的线程
NSBlockOperation *lastBlockOperation = [NSBlockOperation blockOperationWithBlock:^{
[self loadImage:[NSNumber numberWithInt:(count-1)]];
}];
//创建多个线程用于下载其他图片
for (int i=0; i<count-1; ++i) {
//创建多线程操作
NSBlockOperation *blockOperation = [NSBlockOperation blockOperationWithBlock:^{
[self loadImage:[NSNumber numberWithInt:i]];
}];
//设置依赖操作为最后一张图片加载操作,只有最后一张图片加载完成,其他图片才开始陆续加载
[blockOperation addDependency:lastBlockOperation];
[operationQueue addOperation:blockOperation];
}
//将最后一个图片的加载线程加入线程队列
[operationQueue addOperation:lastBlockOperation];
}
GCD中也有一个类似于NSOperationQueue的队列,GCD统一管理整个队列中的任务,GCD是C语言下的框架。
其实在GCD中还有一个特殊队列就是主队列,用来执行主线程上的操作任务。
/*创建一个队列
第一个参数:队列名称
第二个参数:队列类型,DISPATCH_QUEUE_SERIAL串行,DISPATCH_QUEUE_CONCURRENT并发
注意:GCD的queue不是指针类型
*/
dispatch_queue_t serialQueue = dispatch_queue_create("queue1", DISPATCH_QUEUE_SERIAL);
dispatch_queue_t concurrentQueue = dispatch_queue_create("queue2", DISPATCH_QUEUE_CONCURRENT);
/* 使用dispatch_get_global_queue() 方法取得一个全局的并发队列 */
dispatch_queue_t globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
//异步执行队列任务,第一个参数是队列,第二个参数是任务Block
dispatch_async(queue, ^{
[self loadImage:[NSNumber numberWithInt:i]];
});
//同步执行队列任务,第一个参数是队列,第二个参数是任务Block
dispatch_sync(queue, ^{
[self loadImage:[NSNumber numberWithInt:i]];
});
/* 重复执行某个任务,为了不阻塞线程可以使用dispatch_async()包装一下再执行 */
dispatch_apply(size_t iterations, dispatch_queue_t queue, void (^block)(size_t));
/* 单次执行一个任务,此方法中的任务只会执行一次,重复调用也没办法重复执行(单例模式中常用此方法)*/
dispatch_once(dispatch_once_t *predicate, dispatch_block_t block);
/* 常用:延迟delayInSeconds秒后在队列queue执行block操作 */
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC)), dispatch_queue_t queue, dispatch_block_t block);
为什么需要线程同步?因为要解决多线程的资源抢夺的问题
//初始化锁对象
NSLock *myLock = [[NSLock alloc] init];
//加锁
[myLock lock];//加锁后,下面的代码只能有一个线程进入执行
if (_imageNames.count > 0) {
name = [_imageNames lastObject];
[_imageNames removeObject:name];
}
//使用完解锁
[myLock unlock];
//线程同步
@synchronized(self){
if (_imageNames.count > 0) {
name = [_imageNames lastObject];
[_imageNames removeObject:name];
}
}
线程同步就不细讲了,这是一个大块知识。
标签:执行 需要 ack load with 更新 objc 用户创建 在线
原文地址:http://www.cnblogs.com/ming1025/p/6064523.html