Fork me on GitHub
An Guoli's Blog

多线程运用

系列文章:

多线程

多线程 pthread、NSThread

多线程 GCD

多线程 NSOperation

多线程运用

多线程运用

线程同步

所谓线程同步就是为了防止多个线程抢夺同一个资源造成的数据安全问题,所采取的一种措施。当然也有很多实现方法,请往下看:

  • 互斥锁 :给需要同步的代码块加一个互斥锁,就可以保证每次只有一个线程访问此代码块。

OBJECTIVE-C

1
2
3
@synchronized(self) {
//需要执行的代码块
}

SWIFT

1
2
3
objc_sync_enter(self)
//需要执行的代码块
objc_sync_exit(self)
  • 同步执行 :我们可以使用多线程的知识,把多个线程都要执行此段代码添加到同一个串行队列,这样就实现了线程同步的概念。当然这里可以使用 GCD 和 NSOperation 两种方案:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
//GCD
//需要一个全局变量queue,要让所有线程的这个操作都加到一个queue中
dispatch_sync(queue, ^{
NSInteger ticket = lastTicket;
[NSThread sleepForTimeInterval:0.1];
NSLog(@"%ld - %@",ticket, [NSThread currentThread]);
ticket -= 1;
lastTicket = ticket;
});
//NSOperation & NSOperationQueue
//重点: 1. 全局的 NSOperationQueue, 所有的操作添加到同一个queue中
// 2. 设置 queue 的 maxConcurrentOperationCount 为 1
// 3. 如果后续操作需要Block中的结果,就需要调用每个操作的waitUntilFinished,阻塞当前线程,一直等到当前操作完成,才允许执行后面的。waitUntilFinished 要在添加到队列之后!
NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
NSInteger ticket = lastTicket;
[NSThread sleepForTimeInterval:1];
NSLog(@"%ld - %@",ticket, [NSThread currentThread]);
ticket -= 1;
lastTicket = ticket;
}];
[queue addOperation:operation];
[operation waitUntilFinished];
//后续要做的事

延迟执行

所谓延迟执行就是延时一段时间再执行某段代码。下面说一些常用方法。

  • perform
1
2
// 3秒后自动调用self的run:方法,并且传递参数:@"abc"
[self performSelector:@selector(run:) withObject:@"abc" afterDelay:3];
  • GCD

可以使用 GCD 中的 dispatch_after 方法

1
2
3
4
5
6
7
8
// 创建队列
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
// 设置延时,单位秒
double delay = 3;
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delay * NSEC_PER_SEC)), queue, ^{
// 3秒后需要执行的任务
});
  • NSTimer

NSTimer 是iOS中的一个计时器类,除了延迟执行还有很多用法,不过这里直说延迟执行的用法。

1
[NSTimer scheduledTimerWithTimeInterval:3.0 target:self selector:@selector(run:) userInfo:@"abc" repeats:NO];

单例模式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
static HLUserManager *_singleton = nil;
@implementation HLUserManager
+ (instancetype)sharedManager {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_singleton = [[HLUserManager alloc] init];
});
return _singleton;
}
@end

下面看 Swift 中的单例模式,在Swift中单例模式非常简单!想知道怎么从 OC 那么复杂的方法变成下面的写法的,请看这里

SWIFT

1
2
3
4
5
6
class Tool: NSObject {
static let sharedTool = Tool()
// 私有化构造方法,阻止其他对象使用这个类的默认的'()'构造方法
private override init() {}
}

从其他线程回到主线程的方法

我们都知道在其他线程操作完成后必须到主线程更新UI。所以,介绍完所有的多线程方案后,我们来看看有哪些方法可以回到主线程。

  • NSThread
1
2
3
4
5
//Objective-C
[self performSelectorOnMainThread:@selector(run) withObject:nil waitUntilDone:NO];
//Swift
//swift 取消了 performSelector 方法。
  • GCD
1
2
3
4
5
6
7
8
9
//Objective-C
dispatch_async(dispatch_get_main_queue(), ^{
});
//Swift
dispatch_async(dispatch_get_main_queue(), { () -> Void in
})
  • NSOperationQueue
1
2
3
4
5
6
7
8
9
//Objective-C
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
}];
//Swift
NSOperationQueue.mainQueue().addOperationWithBlock { () -> Void in
}