一个正在进行的应用程序 叫进程,一个进程 包括程序里的所有资源
线程是进程的一部分.进程是给线程提供资源的
任何一个程序至少有一个线程,那个程序叫主线程
系统会为线程分配 1兆的 栈空间
多线程是为了执行 并发

线程: 执行任务(代码)的单元
任务: 一个方法,代码段
 1.什么是线程同步?
 同步其实就是串行,线程2的执行依赖于线程1的结果.
 2.如何实现同步:
 建立一个NSOperationQueue,把它的线程最大值设为1
 (方法: setMaxConcurrentOperationCount)

NSThread 线程类  isMainThread它的类方法,用来判断这个线程是不是主线程
凡前面是is的都是布尔值 ,打印的值是1(是组线程)0

线程分两种: 脱离线程 和 非脱离线程
    脱离线程: 执行完任务之后,自动销毁的线程
    非脱离线程: 执行完任务之后,不会被销毁的线程,可以后续执行别的任务
    主线程 是 非脱离线程
    每一个线程都自带一个NSRunLoop对象,runloop默认是关闭的.一旦runloop开启,你的线程就会成为非脱离线程.runloop帮你轮询有没有新的任务分配到了这个线程里面  
 实现多线程的方式一:
  使用 跟类 NSObject 中的 performSelecterXXX方法.
  UI的刷新一定要再主线程里进行子线程刷新UI会异常,刷新不了,或者延迟刷新

   多线程 背后执行 XX方法   .它解决了想立即执行的问题
如:[self performSelectorInBackground:@selector(aa) withObject:nil];
实现多线程的方式二(脱离线程):
使用 NSThread 类
 二的第一个: 它解决了想立即执行的问题
创建一个线程并让线程执行 self aa方法 
 [NSThread detachNewThreadSelector:@selector(aa) toTarget:self withObject:nil];
  [thread start]; 记得写开始执行(可以自己决定什么时候开始执行)
二的第二个:  它解决了想延迟执行的问题 ,就是在方法中调延迟方法,然后最外层的方法再被外界使用
NSThread *thread=[[NSThread alloc] initWithTarget:self selector:@selector(aa) object:nil];
[thread start]; 记得写开始执行(可以自己决定什么时候开始执行)
第三种实现多线程的方式:   NSOperationQueue 操作队列    一个接口 调用的操作
  NSInvocationOperation(程序调用操作)  是一个操作,在需要的时候开辟. 它是一个线程操作,为的是使用它来调一个可用的方法.所以在需要用到的时候添加即可. 然后再把它添加到NSOperationQueue对象上

 NSInvocationOperation *op1=[[NSInvocationOperation alloc] initWithTarget:self selector:@selector(aa) object:nil];    NSBlockOperation *op2=[NSBlockOperation blockOperationWithBlock:^{        NSLog(@"这是一个block operation");    }];     //NSInvocationOperation 是一个操作,在需要的时候,开辟    NSOperationQueue *queue=[[NSOperationQueue alloc] init];    [queue setMaxConcurrentOperationCount:1];//线程最大数
    [queue addOperation:op1]; //一旦把她加到NSOperationQueue,需要start  即:    [op1 start]










 但现在只需要把操作放到队列里即可,不需要人为调用start,queue会根据op的排队情况,帮你调用start.会智能为op安排线程     [queue addOperation:op2];
第四种 实现多线程的方法是GCD

如果一个任务(方法)在子线程里面执行,我们需要在任务里面加自动释放池
 原因: 因为,线程与线程之间 相互独立的.但是资源是共享的,共享 堆空间.如果子线程里开辟了空间,没有释放.其他线程也无法使用这块以及开辟的空间.  
尤其是当子线程里大量使用便利构造器的时候,会导致很多堆空间无法回收内存
所有的autorelease只有遇到自动释放池的时候才会释放,所以任何子线程都要加自动释放池
线程 共享堆.栈不共享! 每个子线程默认的栈大小是512K.主线程栈大小是1M.栈主要是放 局部变量的,局部变量出了方法就会销毁,因此,尽管只有512K或者1M但是以及够用了.栈空间的大小 必须是4k的整数倍.

执行完子线程以后一定要回到主线程 ( 回到主线程 子线程通信)
方法:performSelectorOnMainThreadwithObjectwaitUntilDone:]; //waitUntilDone 等待结束 可以控制执行顺序
如下: 在
@autoreleasepool {  如果在子线程里面需要执行任务,一定要写到自动释放池里面         NSLog(@"+++%d",[NSThread isMainThread]);         for (int i = 0; i < 1000; i++) {             NSLog(@"%d",i);         }         //回到主线程 子线程通信.执行完子线程以后一定要回到主线程         [self performSelectorOnMainThread:@selector(bb) withObject:nil waitUntilDone:YES]; //waitUntilDone 等待结束 可以控制执行顺序         NSLog(@"子线程结束了");      } }