6.0 Introduction (Concurrency)

本文深入探讨了并发编程的概念及其在iOS和OS X应用开发中的应用,着重介绍了Grand Central Dispatch (GCD)的使用方法,包括派遣队列、并发队列、串行队列等核心组件,以及如何使用block对象和operations进行任务调度和执行,以提升应用性能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Concurrency啥意思啊,并发。
本篇,有些是翻译的,有些不会翻译,就用自己的话把大概意思描述出来。

现代的操作系统哪个不支持并发呢,是不是?
单核时代,那是假并发,多核时代,真并发来了。

Grand Central Dispatch, 简称 GCD:底层C API,通过block对象来工作,是用来给不同核分配任务的,程序员根本不用担心到底哪个核执行了该任务。

GCD的核心是派遣队列(dispatch queues)。派遣队列就是在主机上管理线程池,不管在ios上还是在mac上,我们都不能直接使用这些线程,而是操作派遣队列。我们分配任务到这些队列上,让这些队列来执行我们的任务。GCD提供了多种方法来运行这些任务:同步,异步,延时运行,等等。

我们不需要引用某些包来使用GCD,因为苹果已经把它们合并到各个框架里面来了,比如Core Foudation,Cocoa / Cocoa Touch。在GCD的dispatch_关键字里面,所有的方法和数据类型都是有效的。dispatch_async可用来分配任务到队列以便后续异步执行,而dispatch_after可以让你在某个延时之后执行block代码。

如果不用GCD和operations,我们需要创建线程来执行同步任务。比如在ios上我们需要创建类似如下线程来执行1000次的操作:
<书上源码>
- (void) doCalculation{
/* Do your calculation here */
}
- (void) calculationThreadEntry{
@autoreleasepool {
NSUInteger counter = 0;
while ([[NSThread currentThread] isCancelled] == NO){
[self doCalculation];
counter++;
if (counter >= 1000){
break;
}
}
}
}
- (BOOL) application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{
/* Start the thread */
[NSThread detachNewThreadSelector:@selector(calculationThreadEntry)
toTarget:self
withObject:nil];
self.window = [[UIWindow alloc] initWithFrame:
[[UIScreen mainScreen] bounds]];
self.window.backgroundColor = [UIColor whiteColor];
[self.window makeKeyAndVisible];
return YES;
}
我们需要手动启动线程并创建所需的结构(切入点,自动释放池,main函数)。如果我们用GCD来实现,我们只需简单创建block对象并派发给GCD来执行。要在主线程执行还是在子线程执行都有我们来决定。例子:
<书上源码>
dispatch_queue_t queue =
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
size_t numberOfIterations = 1000;dispatch_async(queue, ^(void) {
dispatch_apply(numberOfIterations, queue, ^(size_t iteration){
/* Perform the operation here */
});
});

在本章里面,你将学习到GCD的相关知识,并了解如何去使用它来写出时髦的性能好的app。

首先,先来了解如下几个重要的概念。派遣队列有三种类型:

Main queue  主队列
这个队列在主线程中执行任务。Cocoa和Cocoa Touch要求所有的UI相关的操作都应该在主线中执行。使用dispatch_get_main_queue方法来获取主队列的句柄。

Concurrent queues 并发队列
你可以通过GCD获得很多个队列来执行异步的或同步的任务。多个并发的队列可以并列执行多个任务。使用dispatch_get_global_queue方法来获取并发队列的句柄。

Serial queues 串行队列
这是一种不管你提交的是同步的还是异步的任务,他将按照先入先出法来执行的队列。所以呢,在某个特定的时刻,将只有一个block 对象在执行,而且他们不会在主线程中执行。所以你可以提交一些要严格按照先后顺序执行的任务给它。使用dispatch_queue_create函数来创建串行队列,一旦你使用完对这个队列,你应该用dispath_release方法来释放他。

在任何时候,你都可以使用多个派遣队列。虽然系统中只有一个主队列,但你可以为你的任意的功能需求创建任意多的串行队列。你也可以获取并发队列并配发任务给他们。在派遣队列中,任务有两种形式:block对象或C函数,这将在6.4中介绍。

block对象是对代码的打包,他经常以oc的方法的形式出现。block对象,加上GCD可以创造出性能良好的多线程应用。他们为什么这么特别呢,因为利用他们,你只需把代码交给GCD,让他来看管好代码的执行,而你并不需要手动去创建多线程。
 
注:或许block对象和传统C 函数指针最大的区别是block拷贝了可以访问到的局部变量的值并维护着这份副本。如果这些变量在block范围之外改变了值,你仍然可以确定block自己维护的那个副本的值是没有被改变的。

ob中的block对象在编程领域中被称为一等的对象。你可以动态的编译他们,作为参数传递给方法,也可以作为返回值从方法那边返回。所有的这些使你能够很容易地让程序在运行时实现想要的功能。特别是,block对象可以借助GCD在独立的线程中运行。对为oc对象,block对象跟其他的对象没什么两样。

创建block对象与创建传统的C函数类似,这将在6.1中阐述。block对象可以有返回值,可以传递参数给他。block对象可以定义成内联的形式,也可以是单独的代码块,这也跟C函数类似。当用内联形式创建时,他所能访问到的变量,其处理方式与用单独的代码块实现时是不同的。

GCD与block一同协作,当利用GCD来执行任务时,你可以给他传递block对象。block代码可以同步执行,也可以异步执行,这取决于你使用了GCD的哪个方法。因此,你可以创建block对象来下载资源,而且他可以在应用中多个地方被同步执行方式或异步执行方式调用。而block本身是无需指定是同步的还是异步的。你只要用合适的方法调用它,他就会乖乖的按你的意愿工作。

在编写ios和os X程序时,block对象还是比较新的。事实上,block并没有线程那么流行,这可能是他的语法相对于纯OC方法来说有点难而且有些难于理解的缘故。但尽管如此,block对象是如此强悍以至于苹果花大力气把它集成在自己的库里面,你可能已经经过了,在NSMutableArray里面,我们可以利用它来排序。

这一张主要专注于在iOS和 Mac OSX 应用中创建和使用block对象,使用GCD来为操作系统,线程和定时器调度任务。我想强调的是,想熟悉block对象语法的唯一途径是自己多写一些这方面的代码。看看这一章里面的例子并自己去实现一些block对象。

在这里,你将学到block对象的基础知识,然后是一些比较高级的话题,比如GCD,线程,定时器,Operations,和Operation Queues。在你移步GCD之前,你将学到任何你所需要知道的关于block对象的知识。从我的经验来说,最好的学习block对象的方法是通过例子,所以在这一章中,你将会看到很多的例子。请确保你在你自己的Xcode里面把这些例子给实现了,并真正学到了其语法。

Operations可以配置成同步或异步去运行一段代码。你可以手动管理他们,或是把它们放在Operation queues里面,这样Operation queues就会触发他并发执行,而你并不需要考虑后面的线程管理。在这一章中,你将看到如何使用Operations,和Operation Queues,线程,定时器来同步和异步执行任务。

Cocoa 提供了3种不同类型的Operations:
block operations 这种可触发一个或多个block对象的执行
Invocation operations 这种允许你调用另一个,当前存在的对象的方法
Plain operations 这种是简单的类,需要派生出子类,要执行的代码写在子类的main 函数里面。

Operations 可以用 Operation queues来管理,其类型是NSOperationQueue。当创建好Operation,你可以把它加入到operation queue里面,让他来管理operation。

一个operation 对象可以依赖于另一个operation对象,并在另一个或更多个operation完成后才执行自己的任务。除非你加入这种依赖关系,你是无法控制operation的执行顺序的。假如,你按某种顺序把它们加到队列里面,但这并不保证它们就按照按个顺序执行。

使用operations和operation queues时,有几件重要的事情必须要牢记:
1,operations,默认是在启动它的那个线程中执行的(使用start类方法)。如果你想异步执行,你必须使用operation queue 或在NSoperation的子类的main方法中分离出新的线程来执行。
2,一个operation可以等到另一个operation执行完才启动自己。所以要注意不要创建出相互依赖的operations。一个总所周知的错误就是死锁。
3,operations 是可以取消的。所以,如果你子类化NSOperation并创建一个自定义的Operation对象,在执行任务前,你必须检查下此任务是不是被取消了。比如,你有一个operation的任务是每20秒检查一下网络连接是否正常,你就应该在每次执行检查前先看下任务是不是被取消了。如果任务的执行需要比较长的时间(比如下载文件),你也应该在执行任务前先检查下任务是不是取消了。
4,Operation 对象是遵循KVO(key-value observing)的.我们将在后面的章节讨论Key Value Coding 和 Key Value Obserbing。
5,如果你计划子类化NSOperation并自己提供实现方法,你必须在main函数中自己创建自动释放池,main函数会在start方法中被调用。这个在这章中我们也会讨论到。
6,请保管好你创建的operation的引用。operation queues 并发的特性将使你在把operation交给他之后无法再获得它的引用。

线程和定时器都是对象,NSObject派生出来的类的对象。采用线程比采用定时器更复杂,设置线程循环也比简单的监听定时器触发事件更复杂。在iOS中,操作系统至少为每个应用创建了一个线程,也就是主线程。每个线程和定时器都会加到一个运行循环(run loop)里面。一个run loop,就像它名字所阐明的那样,是可以再里面发生许多不同事情的,定时器可以出发,线程可以运行。对run loop的讨论已经超出本章的范围,但在本章里面会有多处提及。

把run loop想象成这样一个循环,他有自己的起点,在某个状态下会结束,并在其
生命周期里面一系列的事件被触发。线程和定时器都将附属于run loop,实际上他们需要run loop才能工作。

一个应用的主线程是哪个可以操作UI事件的线程。如果你在主线程执行一个需要比较长时间的任务,你会发现你应用的UI将会变得无法响应或是响应很慢。为了避免这种情况,你可以创建独立的线程或定时器来执行任务,这样主线程就不会被阻塞。

 

 

 

 

 

 


 

资源下载链接为: https://pan.quark.cn/s/d9ef5828b597 在本文中,我们将探讨如何通过 Vue.js 实现一个带有动画效果的“回到顶部”功能。Vue.js 是一款用于构建用户界面的流行 JavaScript 框架,其组件化和响应式设计让实现这种交互功能变得十分便捷。 首先,我们来分析 HTML 代码。在这个示例中,存在一个 ID 为 back-to-top 的 div 元素,其中包含两个 span 标签,分别显示“回到”和“顶部”文字。该 div 元素绑定了 Vue.js 的 @click 事件处理器 backToTop,用于处理点击事件,同时还绑定了 v-show 指令来控制按钮的显示与隐藏。v-cloak 指令的作用是在 Vue 实例渲染完成之前隐藏该元素,避免出现闪烁现象。 CSS 部分(backTop.css)主要负责样式设计。它首先清除了一些默认的边距和填充,对 html 和 body 进行了全屏布局,并设置了相对定位。.back-to-top 类则定义了“回到顶部”按钮的样式,包括其位置、圆角、阴影、填充以及悬停时背景颜色的变化。此外,与 v-cloak 相关的 CSS 确保在 Vue 实例加载过程中隐藏该元素。每个 .page 类代表一个页面,每个页面的高度设置为 400px,用于模拟多页面的滚动效果。 接下来是 JavaScript 部分(backTop.js)。在这里,我们创建了一个 Vue 实例。实例的 el 属性指定 Vue 将挂载到的 DOM 元素(#back-to-top)。data 对象中包含三个属性:backTopShow 用于控制按钮的显示状态;backTopAllow 用于防止用户快速连续点击;backSeconds 定义了回到顶部所需的时间;showPx 则规定了滚动多少像素后显示“回到顶部”按钮。 在 V
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值