XMPPFramework中的线程架构、线程安全、内存管理
Version 3的XMPPFramework带来了大量的并行性和极大的性能提升。如何利用呢?
Grand Central Dispatch
编写多线程代码历来是个困难的并且容易引起问题的事情。GCD技术在很大程度上使编写多线程代码变得容易。
GCD技术是苹果的一项新技术。这个技术让我们不用去考虑如何创建一个线程、该创建多少个线程,不用去关心线程数对
性能的影响。
一方面,创建线程是件很昂贵的操作。慢并且开销大。太多的线程切换也浪费CPU时间。
另一方面,系统也不会给出一个简单的的答案告诉你该创建多少个线程才是最合适的。
这些都是和系统的负载有关的,时刻在变化。系统知道确切的负载情况。所以应该交个系统。
GCD利用一个简单的抽象解决了这些问题:
不用再管线程了,现在你只需要使用dispatch queues。它们是超轻量级,你可以创建大量的queue。
GCD库将自动管理合适大小的线程池,并且在线程池中的线程上执行你分派的队列。
因此dispatch_queue并不是一个线程,它只是一个为了让你停止思考线程术语的抽象设计。
看下面的例子:
// Creating a dispatch queue is a lightweight operation.
// Creating a thread = 512 KB
// Creating a queue = 256 Bytes !
//
// We're going to create a serial queue.
dispatch_queue_t myQ = dispatch_queue_create("my q name", NULL);
// Placing a work item in a GCD queue is a lightweight operation.
// In fact, it requires only 15 instructions.
// By comparison, setting up a thread, and assigning work to it
// can require hundreds of instructions
// and take more than 50 times longer.
dispatch_async(myQ, task1);
dispatch_async(myQ, task2);
dispatch_async(myQ, task3);
task1 - task3都运行在一个线程上吗?NO,不要把队列当做一个线程……
有可能是这种情况:
task1 -> Thread D
task2 -> Thread E
task3 -> Thread F
也有可能是这样:
task1 -> Thread Z
task2 -> Thread D
task3 -> Thread Z
这一点并不重要。我们创建了一个串行队列,因此任务会按顺序被执行。 任务2在任务1结束之前不会开始。
通过队列实现并行
XMPPFramework通过允许所有的模块和代理运行在它们自己的队列上来实现并行性。让我们在代码里面来深入的
看看:
无论何时,当你添加一个代理时,你同样需要指定dispatch_queue,这个dispatch_queue是你希望你的代理方法
被调用的地方。
上面的代码指定了代理方法在主线程上被调用。你可以通过创建并指定自己的队列,很容易的并行化你的XMPP处理代码。
当xmppStream要调用你的代理方法时,它是这样做的
避免死锁是简单的 -- 代理总是被异步调用。
线程安全
如果你调用了
[xmppStream addDelegate:self delegateQueue:...];
那么不要忘记在合适的地方(maybe in dealloc, or even before)做如下调用
[xmppStream removeDelegate:self];
这应该应用于任何你可能添加了代理的模块
内存管理
XML是个树形结构。你处理的那些节点有父亲有孩子。XML的API被设计成允许你从上到
下的遍历整棵树。因此,如果你持有某个子节点,整棵树可能都不会被释放。所以应该是
创建一份子节点的拷贝,而不是持有子节点。