1.NSThread与NSRunLoop:
    一个单独的app应用就是一个进程,里面起码包含有一个主线程(UI线程),并可以创建多个子线程
    每个thread中默认会有一个runLoop对象,主线程的runLoop对象是运行着的,用户自己创建的子线程runLoop对象默认是没有启动的。
    如果新开的子线程只是为了完成一个耗时的任务,那么不用启动runLoop循环,如果需要子线程监控一些事情,则需开启;只有给runLoop添加了源才能保证线程一直运行存在,这些源包括timer源、输入事件等,参考:http://www.hrchen.com/2013/06/multi-threading-programming-of-ios-part-1/ 和 http://blog.sina.com.cn/s/blog_74e9d98d0101gzxq.html

2.NSOperationQueue与NSOperation:
    一个operation就相当于一个函数块、block块、代码块,这里只是把它提高到一种任务的角度来看待,然后,任务便会有开始执行(start)、取消(cancel)、是否取消(isCancel)、是否完成(isFinishing)、暂停(pause)等状态函数,其本身是不会创建新的线程来执行它的,NSOperation本身是一个基类,不能直接使用,必须继承它。
    NSOperation中比较重要的是start和main函数,一般结合NSOperationQueue来使用,OperationQueue实质上也就是数组管理,对添加进去的operation进行管理、创建线程等;添加到queue里的operation,queue默认会调用operation的start函数来执行任务,而start函数默认又是调用main函数的。
    如果不想自定义operation,则可以简单使用系统预定义的两个operation子类:NSBlockOperation(任务块是一个block块)、NSInvocationOperation(任务块是一个函数块)
     另外,OperationQueue在使用上也有很大的缺陷,比如一旦operation添加到队列中后,就不能再对operation进行一些修改操作,否则将会出现不可预知的错误,因为operation在队列中有可能随时都会被执行;只能进行cancel或整个队列的cancelAllOperations操作,对单个operation进行cancel后,这个operation还会短暂停留在队列的operations数组里,要稍等片刻才会被移除,这样对于外界使用队列这个operation数组的情况将会出现bug,cancelAllOperations也是要等会才会全部被移除;值得一提的是,cancel和cancelAllOperations默认情况下,都不能取消已经正在执行的operation,只能取消在队列中等待的operation,如果硬要取消正在执行的,只能重写operation的main方法,并在main方法中添加对isCancel属性的监控;而且对于队列的setSuspended方法也只是暂停等待的operation,还有operation添加依赖、队列最大线程数等,功能都比较鸡肋,一切队列的方法都只能对等待的operation才能起作用。
    
    如此一来,特别对于像下载这样的,只能自定义operation对象,并重写start方法(start方法中,不一定仍然调用自身的main方法,可以自己指定执行的方法,像AFURLConnectionOperation一样)、自己创建线程;之前的operation本身是不会创建线程的,线程是在queue中创建,所以才产生并发的效果。
   
   自定义operation需要重写并注意的函数:网上说的那么多重写start main isExcuding实现KVO等  其实都是为了后面结合OperationQueue使用,如果你完全不想使用queue,则operation貌似也没有使用的必要,它本身就是一个代码块,不创建线程的,其start main函数都是为了提供给queue管理调用的,可参考AFURLConnectionOperation的实现
   NSOperation.h头文件:
@interface NSOperation : NSObject {
@private
    id _private;
    int32_t _private1;
#if __LP64__
    int32_t _private1b;
#endif
}

- (id)init; // designated initializer

- (void)start; //
- (void)main;

- (BOOL)isCancelled;
- (void)cancel;

- (BOOL)isExecuting;
- (BOOL)isFinished;

- (BOOL)isConcurrent;

- (BOOL)isReady;

- (void)addDependency:(NSOperation *)op;
- (void)removeDependency:(NSOperation *)op;

- (NSArray *)dependencies;

typedef NS_ENUM(NSInteger, NSOperationQueuePriority) {
    NSOperationQueuePriorityVeryLow = -8L,
    NSOperationQueuePriorityLow = -4L,
    NSOperationQueuePriorityNormal = 0,
    NSOperationQueuePriorityHigh = 4,
    NSOperationQueuePriorityVeryHigh = 8
};

- (NSOperationQueuePriority)queuePriority;
- (void)setQueuePriority:(NSOperationQueuePriority)p;

#if NS_BLOCKS_AVAILABLE
- (void (^)(void))completionBlock NS_AVAILABLE(10_6, 4_0);
- (void)setCompletionBlock:(void (^)(void))block NS_AVAILABLE(10_6, 4_0);
#endif

- (void)waitUntilFinished NS_AVAILABLE(10_6, 4_0);

- (double)threadPriority NS_AVAILABLE(10_6, 4_0);
- (void)setThreadPriority:(double)p NS_AVAILABLE(10_6, 4_0);

@end