何为多线程
线程就是“一个CPU执行的一条无分叉的命令列”。
并发与并行
并发(concurrent)
指的是一种现象,一种经常出现,无可避免的现象。它描述的是“多个任务同时发生,需要被处理”这一现象。侧重点在于“发生”
并行(parallelism)
指的是一种技术,一个同时处理多个任务的技术。他描述了一种能够同时处理多个任务的能力。侧重点在于“运行”
小结: 并发是一种现象,面对这一现象,我们首先创建多个多线程,真正加快程序运行速度的,是并行技术。也就是让多个CPU同时工作。而多线程,是为了让多个CPU同时工作成为可能。
同步与异步
描述的是任务之间的先后顺序问题。
小结:在需要同时处理IO和UI的情况下,真正起作用的是异步,而不是多线程。
GCD
队列
串行队列(FIFO,每次只执行一个)
并发队列(FIFO,多个任务并发)
主队列(特殊的串行队列,一定在主线程中执行)
执行方式
同步执行
异步执行
队列名字 | 同步 | 异步 |
---|---|---|
主队列 | 在主线程中执行 | 在主线程中执行 |
串行队列 | 在当前线程中执行 | 新建线程执行 |
并发队列 | 在当前线程中执行 | 新建线程执行 |
GCD的死锁问题
向当前串行队列中同步派发一个任务
Swift
let mainQueue = DispatchQueue.main
let block = { () in
print("当前线程: \(Thread.current)")
}
mainQueue.sync(execute: block)
OC
dispatch_sync(dispatch_get_main_queue(), ^{
NSLog(@"当前线程 %@", [NSThread currentThread]);
});
主队列在执行dispatch_sync
,随后队列中新增一个任务block
。因为主队列是同步队列,所以block
要等dispatch_sync
执行完才能执行,但是dispatch_sync
是同步派发,要等block
执行完才算是结束。在主队列中的两个任务互相等待,导致了死锁。
GCD任务组
Swift
let group = DispatchGroup()
let serialQueue = DispatchQueue(label: "com")
serialQueue.async(group: group, execute: { () -> Void in
for _ in 0..<2 {
print("group-serial \(Thread.current)")
}
})
serialQueue.async(group: group, execute: { () -> Void in
for _ in 0..<3 {
print("group-02 - %@ \(Thread.current)")
}
})
let workItem = DispatchWorkItem {
print("完成 - \(Thread.current)")
}
group.notify(queue: DispatchQueue.main, work: workItem)
OC
dispatch_group_t group = dispatch_group_create();
dispatch_queue_t serial = dispatch_queue_create("cn.gigahome.w", NULL);
// dispatch_queue_t concurrentQueue = dispatch_queue_create("cn.gigahome.w", DISPATCH_QUEUE_CONCURRENT);
dispatch_group_async(group, serial, ^{
for (int i = 0; i < 2; i++) {
NSLog(@"group serial %@", [NSThread currentThread]);
}
});
dispatch_group_async(group, serial, ^{
for (int i = 0; i < 3; i++) {
NSLog(@"group 02 %@", [NSThread currentThread]);
}
});
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
NSLog(@"完成 %@", [NSThread currentThread]);
});
wait
leave
dispatch_after
Swift
let mainQueue = DispatchQueue.main
let time = DispatchTime.now() + 5.0
print("\(Thread.current)")
mainQueue.asyncAfter(deadline: time) {
print("\(Thread.current)")
}
OC
dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC));
NSLog(@"当前线程 %@", [NSThread currentThread]);
dispatch_after(time, dispatch_get_main_queue(), ^{
NSLog(@"当前线程 %@", [NSThread currentThread]);
});
NSOperation
Swift
let operation = BlockOperation { () -> Void in
print("doSomething1 \(Thread.current)")
}
operation.addExecutionBlock { () -> Void in
print("doSomething2 \(Thread.current)")
}
operation.start()
OC
NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"%@", [NSThread currentThread]);
}];
[operation addExecutionBlock:^{
NSLog(@"execution block %@", [NSThread currentThread]);
}];
[operation start];
NSOperationQueue
队列名字 | NSOperationQueue | GCD |
---|---|---|
主队列 | OperationQueue.main | DispatchQueue.main |
串行队列 | 自建队列maxConcurrentOperationCount为1 | DispatchQueue(label: "") |
并发队列 | 自建队列maxConcurrentOperationCount大于1 | DispatchQueue(label: "",attributes:.concurrent) |
NSOperationQueue会为每一个NSOperation建立线程并调用他们的start方法
Swift
let queue = OperationQueue()
queue.maxConcurrentOperationCount = 3
let operation = BlockOperation { () -> Void in
print("exec block1 -- \(Thread.current)")
}
operation.addExecutionBlock { () -> Void in
print("exec block2 -- \(Thread.current)")
}
operation.addExecutionBlock { () -> Void in
print("exec block3 -- \(Thread.current)")
}
queue.addOperation(operation)
print("操作结束")
OC
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
queue.maxConcurrentOperationCount = 3;
NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"exec block1 -- %@", [NSThread currentThread]);
}];
[operation addExecutionBlock:^{
NSLog(@"exec block2 -- %@", [NSThread currentThread]);
}];
[operation addExecutionBlock:^{
NSLog(@"exec block3 -- %@", [NSThread currentThread]);
}];
[queue addOperation:operation];
NSLog(@"操作结束");
NSOperation新特性
取消任务
operation.cancel()
queue.cancelAllOperations()
设置依赖
operation2.addDependency(operation)
NSOperationQueue的暂停与恢复
queue.suspended = true(挂起)
queue.suspended = false(恢复)
NSOperation的优先级
typedef NS_ENUM(NSInteger, NSOperationQueuePriority) {
NSOperationQueuePriorityVeryLow = -8L,
NSOperationQueuePriorityLow = -4L,
NSOperationQueuePriorityNormal = 0,
NSOperationQueuePriorityHigh = 4,
NSOperationQueuePriorityVeryHigh = 8
};
public enum QueuePriority : Int {
case veryLow
case low
case normal
case high
case veryHigh
}
NSOperationQueue
也不能完全保证优先级高的任务一定先执行。
NSOperation和GCD如何选择
GCD以block为单位,代码简洁。同时GCD中的队列、组、信号量、source、barriers都是组成并行编程的基本原语。
对于一次性的计算,或是仅仅为了加快现有方法的运行速度,选择轻量化的GCD更加方便
NSOperation可以用来规划一组任务之间的依赖关系,设置他们的优先级,任务能别取消。队列可以暂停、恢复。NSOperation还可以子类化。
其它
dispatch_suspend
和dispatch_resume
dispatch_suspend(queue) //暂停某个队列
dispatch_resume(queue) //恢复某个队列
dispathc_once
+ (Manager *)sharedInstance {
static Manager *sharedManagerInstance = nil;
static dispatch_once_t once;
dispatch_once(&once, ^{
sharedManagerInstance = [[Manager alloc] init];
});
return sharedManagerInstance;
}
dispatch_barrier_async
dispatch_async(queue, block1_for_reading)
dispatch_async(queue, block2_for_reading)
dispatch_barrier_async(queue, block_for_writing)
dispatch_async(queue, block3_for_reading)
dispatch_async(queue, block4_for_reading)
dispatch_semaphore
let queue = DispatchQueue.init(label: "cn.gigahome.w", attributes: DispatchQueue.Attributes.concurrent)
queue.async {
print("读数据1")
}
queue.async {
print("读数据2")
}
let workItem = DispatchWorkItem.init(qos: DispatchQoS.default, flags: DispatchWorkItemFlags.barrier) {
print("开始写数据------写数据完成")
}
queue.async(execute: workItem)
queue.async {
print("读数据3")
}
queue.async {
print("读数据4")
}
网友评论