有了域名和空间怎么建网站,哪些公司需要网页电商设计师,成都微信小程序开发平台,做地理题的网站一、进程#xff08;Process#xff09;
在 iOS 开发中#xff0c;进程是一个基本的概念#xff0c;虽然通常作为开发者#xff0c;你不需要像在某些其他操作系统那样进行直接的进程管理#xff0c;因为 iOS 提供了很多高级别的抽象。不过#xff0c;了解进程的概念对于…一、进程Process
在 iOS 开发中进程是一个基本的概念虽然通常作为开发者你不需要像在某些其他操作系统那样进行直接的进程管理因为 iOS 提供了很多高级别的抽象。不过了解进程的概念对于理解应用程序的运行环境仍然很重要。
1.进程定义
进程是一个执行中的程序的实例。它是系统资源如 CPU 时间、内存空间、文件描述符等分配的基本单位。每个进程都运行在其自己的隔离空间内操作系统负责管理进程的生命周期以及它们对系统资源的使用。 2.iOS进程特点
沙盒环境
出于安全考虑iOS 上的每个应用程序都运行在一个称为“沙盒”的隔离环境中。这意味着应用程序只能访问分配给自己的文件系统目录并受限于对设备其他部分的访问。这有助于防止恶意软件破坏系统或窃取数据。
单进程模型
iOS 应用通常作为单个进程运行。尽管应用可以启动多个线程但它们都是属于同一个进程的。
生命周期管理
iOS 操作系统严格管理应用进程的生命周期。应用程序状态如启动、挂起、恢复、终止由系统根据资源需求和用户行为管理。
后台执行限制
为了保持电池寿命和系统性能iOS 对后台进程的执行有严格的限制。应用程序通常情况下在退到后台后会被挂起除非它们声明了后台执行的任务。
内存管理
iOS 使用引用计数如 ARC - Automatic Reference Counting来管理内存。当系统内存不足时它会自动终止后台进程来释放资源。
接口限制
iOS 应用程序不能直接调用大多数系统调用而是通过 iOS SDK 提供的 API 与操作系统交互。这些 API 为进程间通信、资源访问等提供了接口。 3.进程间通信
在 iOS 中进程间通信被限制和控制但仍然提供了几种机制
URL Schemes应用可以注册 URL schemes 来与其他应用交互。UIActivityViewController允许用户在不同的应用之间分享内容。Universal Links通过网页链接直接打开应用提供更加无缝的体验。App Extensions允许应用在某些受限的环境中如通知中心、键盘扩展等提供功能。Handoff支持在不同设备的同一应用之间继续任务。共享容器允许同一开发者的多个应用共享数据。 二、线程Thread 在iOS开发中线程是一个比进程更轻量级的执行单元。一个进程内可以有多个线程它们共享进程的内存空间和资源但是每个线程拥有自己的执行序列、栈空间和线程状态。线程可以并行或并发地执行多个任务从而提高应用程序的效率和响应性。
线程是操作系统能够进行运算调度的最小单位。它被包含在进程之中是进程中的实际运作单位。
1.线程的基本概念
线程隔离
每个线程都有自己的私有栈空间执行上下文和程序计数器。
创建成本
线程的创建和上下文切换比进程轻量得多。
资源共享
同一进程下的线程共享进程的内存和资源。
同步机制
为了防止数据冲突通常需要通过锁、信号量等同步机制来控制线程对共享资源的访问。 2.iOS中的线程管理
iOS提供了几种不同的方式来管理和使用线程
(1).POSIX Threads (pthreads)
这是一种跨平台的线程API允许更精细的线程控制。但它不提供自动内存管理并且使用起来比较复杂。
Swift:
import Foundation// 线程执行的函数
func threadFunction(arg: UnsafeMutableRawPointer?) - UnsafeMutableRawPointer? {print(Thread is now running)// 执行一些任务print(Thread finishing)return nil
}// 创建线程
var thread pthread_t(bitPattern: 0)
var attribute pthread_attr_t()pthread_attr_init(attribute)
pthread_create(thread, attribute, { arg inreturn threadFunction(arg: arg)
}, nil)
pthread_attr_destroy(attribute)// 等待线程结束
pthread_join(thread!, nil)
OC:
#import Foundation/Foundation.h
#import pthread.hvoid *threadFunction(void *arg) {NSLog(Thread is now running);// 执行一些任务NSLog(Thread finishing);return NULL;
}int main(int argc, const char * argv[]) {autoreleasepool {pthread_t thread;pthread_attr_t attribute;pthread_attr_init(attribute);pthread_create(thread, attribute, threadFunction, NULL);pthread_attr_destroy(attribute);// 等待线程结束pthread_join(thread, NULL);}return 0;
}
(2).NSThread
NSThread是Objective-C提供的面向对象的线程操作方式。它相对于pthreads简单一些但仍然需要开发者手动管理线程的生命周期和同步。
Swift:
import Foundation// 线程调用的方法
objc class ThreadExample: NSObject {objc func threadMethod() {print(Thread is now running)// 执行一些任务print(Thread finishing)}
}// 创建并启动线程
let example ThreadExample()
let thread Thread(target: example, selector: #selector(ThreadExample.threadMethod), object: nil)
thread.start()// 主线程继续执行其它任务
print(Main thread is not blocked)
OC:
#import Foundation/Foundation.hinterface ThreadExample : NSObject
- (void)threadMethod;
endimplementation ThreadExample
- (void)threadMethod {autoreleasepool {NSLog(Thread is now running);// 执行一些任务NSLog(Thread finishing);}
}
endint main(int argc, const char * argv[]) {autoreleasepool {ThreadExample *example [[ThreadExample alloc] init];NSThread *thread [[NSThread alloc] initWithTarget:example selector:selector(threadMethod) object:nil];[thread start];// 主线程继续执行其它任务NSLog(Main thread is not blocked);}return 0;
}
(3).Grand Central Dispatch (GCD)
GCD是Apple推荐的多线程解决方案它使用队列来抽象线程的创建和管理。GCD可以自动管理线程池优化线程数量并提供了简单的API来执行异步任务。
Swift:
import Foundation// 创建串行队列
let serialQueue DispatchQueue(label: com.example.serialQueue)// 创建并发队列
let concurrentQueue DispatchQueue(label: com.example.concurrentQueue, attributes: .concurrent)// 在串行队列上异步执行任务
serialQueue.async {for i in 1...3 {print(Serial Queue Async Task \(i))}
}// 在并发队列上异步执行任务
concurrentQueue.async {for i in 1...3 {print(Concurrent Queue Async Task \(i))}
}// 在主队列上延迟执行任务
DispatchQueue.main.asyncAfter(deadline: .now() 2.0) {print(This task is run on the main queue after 2 seconds)
}// 使用全局并发队列
DispatchQueue.global().async {print(Global queue async task)
}// 主线程继续执行其他任务
print(Main thread is not blocked)
下面示例代码的打印顺序?
override func viewDidLoad() {super.viewDidLoad()DispatchQueue.main.async {print(1)}print(2)// 创建串行队列let serialQueue DispatchQueue(label: com.example.serialQueue)// 在串行队列上异步执行任务serialQueue.async {print(3)}print(4)// 创建并发队列let concurrentQueue DispatchQueue(label: com.example.concurrentQueue, attributes: .concurrent)// 在并发队列上异步执行任务concurrentQueue.async {print(5)}print(6)DispatchQueue.global().sync {print(7)}print(8)// 获取一个后台队列优先级为默认let backgroundQueue DispatchQueue.global(qos: .background)// 在后台队列上异步执行任务backgroundQueue.async {// 放置后台线程需要执行的任务print(9)}print(10)DispatchQueue.global().async {print(11)}print(12)}
DispatchQueue.main.async { print(1) } 这个异步调用将任务排队到主队列但是它不会立即执行。由于当前代码块已经在主线程上执行viewDidLoad所以这个异步任务将会在当前代码块完成后的某个时间点执行。serialQueue.async { print(3) } 在一个自定义的串行队列上异步执行。它将会在某个不确定的时间点执行因为它不会阻塞当前线程。但由于它是串行队列它会保证按照被添加到队列中的顺序执行。concurrentQueue.async { print(5) } 在一个自定义并发队列上异步执行。它可能几乎立即开始执行但实际的执行时间取决于系统的调度。DispatchQueue.global().sync { print(7) } 在全局并发队列上同步执行这将会阻塞主线程直到这个同步任务完成所以 print(7) 会在 print(6) 之后而且在 print(8) 之前执行。backgroundQueue.async { print(9) } 在一个全局队列上异步执行这个队列的优先级是后台。它将在未来某个不确定的时间点执行不会阻塞主线程。但由于QoS 级别是一个提示给系统的优先级标识用于决定哪些任务应该先执行。.background QoS 是最低的优先级所以执行顺序会靠后。DispatchQueue.global().async { print(11) } 在全局并发队列上异步执行它会在未来某个不确定的时点执行。
综上所述同步执行的 print 调用将按顺序立即打印按照 2, 4, 6, 7, 8, 10, 12 的顺序。异步派发的任务print(1)确定会在最后打印. 其它的print(3), print(5), print(9), 和 print(11) 将在未来某个时点执行它们的执行顺序取决于系统对任务的调度和队列的类型串行或并发, 但print(9)级别最低会在最后执行。因此其他异步任务的执行顺序是不确定的。
实际打印顺序为:
2/4/3/6/5/7/8/10/12/11/9/1
也打印成这种:
2/4/6/7/8/3/5/10/12/11/9/1
也会打印成这种 :
2/4/6/3/5/7/8/10/12/11/9/1
OC:
#import Foundation/Foundation.hint main(int argc, const char * argv[]) {autoreleasepool {// 创建串行队列dispatch_queue_t serialQueue dispatch_queue_create(com.example.serialQueue, DISPATCH_QUEUE_SERIAL);// 创建并发队列dispatch_queue_t concurrentQueue dispatch_queue_create(com.example.concurrentQueue, DISPATCH_QUEUE_CONCURRENT);// 在串行队列上异步执行任务dispatch_async(serialQueue, ^{for (int i 1; i 3; i) {NSLog(Serial Queue Async Task %d, i);}});// 在并发队列上异步执行任务dispatch_async(concurrentQueue, ^{for (int i 1; i 3; i) {NSLog(Concurrent Queue Async Task %d, i);}});// 在主队列上延迟执行任务dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{NSLog(This task is run on the main queue after 2 seconds);});// 使用全局并发队列dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{NSLog(Global queue async task);});// 主线程继续执行其他任务NSLog(Main thread is not blocked);}return 0;
}
(4).Operation Queues
Operation Queues是基于GCD但更高层次的抽象。它使用NSOperation对象来表示单个任务可以设置任务的依赖关系并通过NSOperationQueue来管理任务的执行。
Swift:
import Foundation// 创建一个操作队列
let operationQueue OperationQueue()// 创建一个NSBlockOperation来执行任务
let operation1 BlockOperation {print(Operation 1 is being executed)// 模拟一些工作Thread.sleep(forTimeInterval: 2)print(Operation 1 has finished executing)
}// 创建另一个操作
let operation2 BlockOperation {print(Operation 2 is being executed)// 模拟一些工作Thread.sleep(forTimeInterval: 1)print(Operation 2 has finished executing)
}// 添加操作依赖operation2将会在operation1完成后才开始执行
operation2.addDependency(operation1)// 将操作添加到队列中
operationQueue.addOperation(operation1)
operationQueue.addOperation(operation2)// 添加一个操作到队列中使用addOperation的闭包形式
operationQueue.addOperation {print(Operation 3 is being executed)// 执行一些工作print(Operation 3 has finished executing)
}// 主线程继续执行其他任务
print(Main thread is not blocked)
OC:
#import Foundation/Foundation.hint main(int argc, const char * argv[]) {autoreleasepool {// 创建操作队列NSOperationQueue *operationQueue [[NSOperationQueue alloc] init];// 创建NSBlockOperation来执行任务NSBlockOperation *operation1 [NSBlockOperation blockOperationWithBlock:^{NSLog(Operation 1 is being executed);// 模拟一些工作[NSThread sleepForTimeInterval:2];NSLog(Operation 1 has finished executing);}];// 创建另一个操作NSBlockOperation *operation2 [NSBlockOperation blockOperationWithBlock:^{NSLog(Operation 2 is being executed);// 模拟一些工作[NSThread sleepForTimeInterval:1];NSLog(Operation 2 has finished executing);}];// 添加操作依赖operation2将会在operation1完成后才开始执行[operation2 addDependency:operation1];// 将操作添加到队列中[operationQueue addOperation:operation1];[operationQueue addOperation:operation2];// 使用addOperationWithBlock添加另一个操作到队列中[operationQueue addOperationWithBlock:^{NSLog(Operation 3 is being executed);// 执行一些工作NSLog(Operation 3 has finished executing);}];// 主线程继续执行其他任务NSLog(Main thread is not blocked);}return 0;
} 3.线程的同步
由于线程共享内存和资源同步变得非常重要。
iOS提供了多种同步机制来避免数据竞争和条件竞争
(1).锁Locks
如NSLock、NSRecursiveLock、NSCondition等用于控制对共享资源的访问。
Swift
import Foundationvar sharedResource [String]()let lock NSLock()func accessSharedResource() {lock.lock()// 安全地访问共享资源sharedResource.append(Data)lock.unlock()
}// 在不同的线程中调用accessSharedResource()
DispatchQueue.global().async {accessSharedResource()
}DispatchQueue.global().async {accessSharedResource()
}
OC
#import Foundation/Foundation.hNSMutableArray *sharedResource [NSMutableArray array];NSLock *lock [[NSLock alloc] init];void accessSharedResource() {[lock lock];// 安全地访问共享资源[sharedResource addObject:Data];[lock unlock];
}// 在不同的线程中调用accessSharedResource()
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{accessSharedResource();
});dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{accessSharedResource();
});
(2).信号量Semaphores
GCD中的dispatch_semaphore_t可以用来控制对资源的并发访问。
Swift
import Foundationlet semaphore DispatchSemaphore(value: 1)func accessSharedResourceWithSemaphore() {semaphore.wait() // 等待信号量// 安全地访问共享资源sharedResource.append(Data)semaphore.signal() // 释放信号量
}// 在不同的线程中调用accessSharedResourceWithSemaphore()
DispatchQueue.global().async {accessSharedResourceWithSemaphore()
}DispatchQueue.global().async {accessSharedResourceWithSemaphore()
}
OC
#import Foundation/Foundation.hdispatch_semaphore_t semaphore dispatch_semaphore_create(1);void accessSharedResourceWithSemaphore() {dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER); // 等待信号量// 安全地访问共享资源[sharedResource addObject:Data];dispatch_semaphore_signal(semaphore); // 释放信号量
}// 在不同的线程中调用accessSharedResourceWithSemaphore()
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{accessSharedResourceWithSemaphore();
});dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{accessSharedResourceWithSemaphore();
});
(3).原子操作
如OSAtomic系列函数提供了简单的原子性操作。
#import libkern/OSAtomic.h__block volatile int32_t counter 0;void incrementCounter() {OSAtomicIncrement32(counter);
}// 在不同的线程中调用incrementCounter()
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{incrementCounter();
});dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{incrementCounter();
});
(4).synchronized
Objective-C中的关键字可以简化锁的使用。
#import Foundation/Foundation.hvoid accessSharedResourceWithSynchronized() {synchronized(sharedResource) {// 安全地访问共享资源[sharedResource addObject:Data];}
}// 在不同的线程中调用accessSharedResourceWithSynchronized()
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{accessSharedResourceWithSynchronized();
});dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{accessSharedResourceWithSynchronized();
}); 4.主线程和后台线程
iOS中有一个特别重要的线程概念是主线程Main Thread
主线程
用于更新UI和处理UI事件以保证用户界面的流畅性。
Swift:
DispatchQueue.main.async {// 更新UI// 例如更新一个标签的文本// self.label.text Updated Text
}
OC:
dispatch_async(dispatch_get_main_queue(), ^{// 更新UI// 例如更新一个标签的文本// self.label.text Updated Text;
});
后台线程
用于执行耗时的任务如网络请求或大量数据处理避免阻塞主线程。
Swift:
DispatchQueue.global(qos: .background).async {// 在这里执行耗时的任务// 例如进行一个网络请求或大量数据处理let result Some Result// 当需要更新UI时回到主线程DispatchQueue.main.async {// 更新UI// self.label.text result}
}
OC:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{// 在这里执行耗时的任务// 例如进行一个网络请求或大量数据处理NSString *result Some Result;// 当需要更新UI时回到主线程dispatch_async(dispatch_get_main_queue(), ^{// 更新UI// self.label.text result;});
});
开发者应该始终记住在主线程上更新UI并将耗时的工作放在后台线程上执行。例如使用GCD可以很容易地在后台执行任务
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{// 在后台线程上执行耗时任务// ...dispatch_async(dispatch_get_main_queue(), ^{// 回到主线程更新UI// ...});
}); 在iOS开发中合理使用线程对于创建流畅、响应式的应用至关重要。避免在主线程上执行耗时操作以及处理好线程间的同步和通信是高效iOS应用程序的标志。
在 Swift 和 Objective-C 这两种 iOS 主要的编程语言中线程使用的概念和操作都是相似的。 三、队列Queue
队列可以被视为对线程行为的一层抽象但它们并不是线程本身。
队列提供了一种机制来组织和调度执行任务的顺序而不需要开发者直接管理线程的创建、同步和其他复杂的线程生命周期问题。 当你操控队列时你实际上是在告诉系统如何安排这些任务的执行。在iOS中这通常是通过使用Grand Central Dispatch (GCD) 来实现的。GCD后台自动管理着一个线程池并根据系统的负载动态地调整线程的使用。这意味着
当你向一个队列中添加任务时你并不需要指定具体运行在哪个线程上GCD会为你处理这些细节。如果任务被添加到串行队列GCD会保证这些任务按照他们被添加的顺序一个接一个地运行。如果任务被添加到并发队列GCD会同时运行多个任务但具体并行的任务数目会由系统根据当前的负载情况来决定。对于主队列主线程的队列GCD会保证所有的任务都在主线程上执行通常用于UI更新以确保界面的流畅性。
由于队列抽象了线程的管理所以开发者不需要也不应该去假设某个任务会在特定的线程上执行。相反应该关注的是任务的组织、同步和他们的执行方式串行或并发。
总之通过操作队列你间接地管理了线程的行为但你并没有直接操控线程。队列的抽象让你能够更专注于任务的逻辑本身而不是底层的线程管理。这极大地简化了并发编程并提高了代码的安全性和可维护性。 1.队列类型 (1).串行队列(Serial Queue)
一次只执行一个任务。下一个任务必须等待当前任务完成后才能开始。任务按照添加到队列的顺序依次执行。保证任务执行的顺序性和排他性。 (2).并发队列(Concurrent Queue)
可以同时执行多个任务。但是任务的开始仍然按照它们被添加到队列的顺序。任务可以并行执行不保证任务的开始和结束顺序。适合执行互不依赖的任务。 (3).主队列Main Queue
主队列是一个特殊的串行队列它用于在主线程上执行任务。由于它在主线程上执行任务因此它通常用于更新 UI 或处理 UI 事件以确保用户界面的更新是平滑且同步的。
获取主队列的方式如下
Swift:
let mainQueue DispatchQueue.main
使用 DispatchQueue.main你可以将任务异步或同步地派发到主线程。通常你会异步地将任务派发到主线程以避免阻塞当前线程
DispatchQueue.main.async {// 更新UI等主线程任务
}
请注意尽管你可以同步地派发任务到主队列但如果你在主线程上这样做将会导致死锁因为主线程会等待自己完成任务这是一个逻辑错误。因此通常你只会异步地将任务派发到主队列。
OC:
dispatch_queue_t mainQueue dispatch_get_main_queue(); (4).全局并行队列Global Concurrent Queues
GCD 提供了几个不同优先级的全局并行队列这些队列在应用程序是共享的。你可以使用它们来执行并发任务而不需要自己创建并行队列。全局并行队列有四个优先级高、默认、低和后台。
获取全局并行队列的方式如下
Swift
let globalQueue DispatchQueue.global(qos: .default)
OC
dispatch_queue_t globalQueue dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
优先级可以是以下之一
DISPATCH_QUEUE_PRIORITY_HIGHDISPATCH_QUEUE_PRIORITY_DEFAULTDISPATCH_QUEUE_PRIORITY_LOWDISPATCH_QUEUE_PRIORITY_BACKGROUND (5).自定义队列Custom Queues
在iOS开发中使用Grand Central Dispatch (GCD)可以创建自定义队列Custom Queues。自定义队列可以是串行的也可以是并行的取决于你的需求。以下是创建自定义队列的基本步骤和示例
创建串行队列
串行队列Serial Queue保证任务按照添加到队列中的顺序执行一个接一个地执行。
Swift:
// 创建自定义串行队列
let serialQueue DispatchQueue(label: com.example.mySerialQueue)// 异步添加任务到队列
serialQueue.async {// 这里添加需要执行的任务print(Task 1 started)// 假设这里有一些耗时操作print(Task 1 finished)
}serialQueue.async {// 添加另一个任务print(Task 2 started)// 同样这里可能有耗时操作print(Task 2 finished)
}// Task 1 和 Task 2 将按照添加的顺序执行
OC:
// 创建自定义串行队列
dispatch_queue_t serialQueue dispatch_queue_create(com.example.mySerialQueue, DISPATCH_QUEUE_SERIAL);// 异步添加任务到队列
dispatch_async(serialQueue, ^{NSLog(Task 1 started);// 假设这里有一些耗时操作NSLog(Task 1 finished);
});dispatch_async(serialQueue, ^{NSLog(Task 2 started);// 同样这里可能有耗时操作NSLog(Task 2 finished);
});// Task 1 和 Task 2 将按照添加的顺序执行
创建并行队列
并行队列Concurrent Queue允许多个任务并发执行。任务开始的顺序仍然符合其被添加到队列中的顺序但是它们的执行和结束顺序可能是不一致的因为任务可以在不同的线程上并发运行。
Swift:
// 创建自定义并行队列
let concurrentQueue DispatchQueue(label: com.example.myConcurrentQueue, attributes: .concurrent)// 异步添加任务到队列
concurrentQueue.async {// 添加任务print(Task 1 started)// 假设耗时操作print(Task 1 finished)
}concurrentQueue.async {// 添加另一个任务print(Task 2 started)// 假设耗时操作print(Task 2 finished)
}// Task 1 和 Task 2 可能会同时执行
OC:
// 创建自定义并行队列
dispatch_queue_t concurrentQueue dispatch_queue_create(com.example.myConcurrentQueue, DISPATCH_QUEUE_CONCURRENT);// 异步添加任务到队列
dispatch_async(concurrentQueue, ^{NSLog(Task 1 started);// 假设耗时操作NSLog(Task 1 finished);
});dispatch_async(concurrentQueue, ^{NSLog(Task 2 started);// 假设耗时操作NSLog(Task 2 finished);
});// Task 1 和 Task 2 可能会同时执行
设置队列的优先级
自定义队列还可以设置服务质量Quality of ServiceQoS以指示任务的重要性和执行优先级。
Swift:
// 创建具有优先级的自定义串行队列
let highPriorityQueue DispatchQueue(label: com.example.myHighPriorityQueue, qos: .userInitiated)// 用户初始化的任务通常比较紧急但不会阻塞UI比如加载操作
highPriorityQueue.async {// 执行高优先级任务
}
服务质量QoS选项包括
.userInteractive: 需要立即结果的任务用于更新UI、处理事件等。.userInitiated: 用户期望立即得到结果的任务比如滑动停止后的加载操作。.default: 默认优先级如果没有设置QoS则队列会使用这个。.utility: 长时间运行的任务通常带有用户可见的进度指示如下载文件。.background: 用户不直接感知的任务比如数据库维护、数据备份等。.unspecified: 没有设置QoS。
通过设置不同的QoS系统会为这些任务分配不同的资源从而影响它们的执行优先级。
OC:
// 创建具有优先级的自定义串行队列
dispatch_queue_attr_t qosAttribute dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_SERIAL, QOS_CLASS_USER_INITIATED, 0);
dispatch_queue_t highPriorityQueue dispatch_queue_create(com.example.myHighPriorityQueue, qosAttribute);// 用户初始化的任务通常比较紧急但不会阻塞UI比如加载操作
dispatch_async(highPriorityQueue, ^{// 执行高优先级任务NSLog(High priority task is being executed.);
}); 2.同步和异步执行
在GCD中你可以选择同步sync或异步async地将任务添加到队列中 同步 (sync)
在当前线程中执行任务并阻塞该线程直到任务完成。
Swift:
// 获取一个队列非主队列
let queue DispatchQueue(label: com.example.queue)// 同步执行任务
queue.sync {// 这个任务会立即执行并且调用线程会等待直到任务完成
}// 这行代码只有在上面的同步任务完成后才会执行注意不要在主队列上同步提交任务因为这会导致死锁。
OC:
dispatch_sync(queue, ^{// 这个任务会立即执行并且提交任务的线程会等待直到任务完成
});// 这行代码只有在上面的任务完成后才会执行
使用同步执行时要特别注意如果你在主队列主线程的串行队列上同步提交任务将会导致死锁因为主队列等待这个同步任务完成而同步任务又在等待主队列也就是它自己空闲从而形成了相互等待的局面。 异步 (async)
允许任务在另一线程中执行不会阻塞当前线程调用线程会等待任务完成。
Swift:
// 获取一个队列
let queue DispatchQueue(label: com.example.queue)// 异步执行任务
queue.async {// 这个任务会被加入队列中但不一定会立即执行
}// 这行代码会在上面的异步任务提交后立即执行而不会等待那个任务结束OC:
dispatch_async(queue, ^{// 这个任务会被加入队列中但不会立即执行
});// 这行代码会在上面的异步任务提交后立即执行而不会等待那个任务结束
异步执行是并发程序设计中的一项基本技术允许多个任务并行进行。在 GCD 中异步提交到串行队列将使任务一个接一个地执行而异步提交到并发队列则可以让多个任务同时进行。 3.队列的选择和使用 在iOS开发中选择合适的队列和执行方式同步或异步对于保证应用性能和响应性至关重要。以下是一些基本指南
使用全局并发队列执行耗时的后台任务如数据处理或网络请求。使用主队列更新UI或执行需要在主线程完成的任务确保UI更新是安全的。使用自定义串行队列来执行需要顺序执行的任务或者当你需要创建一个锁或者保护资源的访问时。使用自定义并发队列来自定义任务的并发执行或者当你需要控制执行任务的优先级时。使用同步执行来等待当前任务完成这通常在你需要立即得到任务结果时使用。使用异步执行来允许当前线程继续工作不需要等待任务完成这有助于避免阻塞UI或者响应用户交互。 四、任务Task
在iOS开发中任务一词通常指的是需要完成的工作单元。任务可以是任何事情从简单的计算到复杂的网络请求。iOS提供了几种不同的方式来处理任务尤其是在多线程和并发编程方面。
以下是一些iOS开发中任务的基本概念和处理方式。 1.任务的类型
计算密集型任务
这些任务需要大量的CPU资源来进行计算。
例子图像处理大量数据计算。 I/O密集型任务
这些任务包括文件读写、网络请求等它们通常等待系统资源的响应。
例子从硬盘读取文件从服务器下载数据。 UI更新任务
这些任务涉及更新用户界面必须在主线程上执行。
例子刷新表视图更新进度条。 2.GCD中的任务
在Grand Central Dispatch (GCD)中任务通常以两种形式提交给队列
同步执行Synchronous Execution
dispatch_sync函数用于同步添加任务到指定的队列。调用线程会停止执行直到任务在队列中完成。这种方式可能会导致死锁尤其是当在主队列上同步提交任务时。 异步执行Asynchronous Execution
dispatch_async函数用于异步添加任务到指定的队列。调用线程不会等待任务完成可以继续执行其他工作。异步执行是实现并发的主要方式。 使用GCD
创建任务
let queue DispatchQueue(label: com.example.myQueue, attributes: .concurrent)queue.async {// 执行耗时的任务let result performCalculations()DispatchQueue.main.async {// 在主线程更新UIupdateUI(with: result)}
}
任务的取消和暂停
在GCD中你不能直接取消已经在执行的任务但是你可以通过在任务代码中添加取消检查点来协作地取消任务。
let queue DispatchQueue(label: com.example.myQueue)
var isCancelled falsequeue.async {if isCancelled { return }// 执行任务
}// 取消任务
isCancelled true 3.NSOperation中的任务
NSOperation是另一种用于执行任务的抽象它比GCD提供更多的控制和灵活性。任务以NSOperation对象的形式表示可以添加到NSOperationQueue中执行。
NSOperation
是一个抽象类需要使用其子类NSBlockOperation或自定义子类。可以设置完成块、添加依赖以及观察任务状态。 NSOperationQueue
管理一组NSOperation对象的执行。可以控制并发操作的数量以及启动、暂停、取消操作。 使用NSOperation
创建任务
let queue OperationQueue()let operation BlockOperation {// 执行耗时的任务let result performCalculations()OperationQueue.main.addOperation {// 在主线程更新UIupdateUI(with: result)}
}queue.addOperation(operation)
任务的取消和暂停
在NSOperation中你可以使用cancel方法来请求取消一个操作操作对象会检查isCancelled属性决定是否提前结束任务。
let operation BlockOperation {// 执行任务if operation.isCancelled {return}// 继续执行任务
}operationQueue.addOperation(operation)// 取消操作
operation.cancel() 4.任务的挑战
在处理任务时开发者必须注意以下几个挑战
线程安全
确保在多线程环境中共享资源的访问是安全的例如使用锁或串行队列。
性能
合理利用多线程和并发避免过多地创建线程导致的上下文切换开销。
死锁
避免因同步执行或资源竞争造成的死锁情况。
资源管理
合理分配和回收资源如内存、文件句柄等。
用户体验
确保耗时操作不会阻塞主线程影响UI的流畅度。