UI:多线程 、用GCD创建线程

什么是应用(程序):就是我们编写的代码编译后生成的app文件

进程:凡是一个运行的程序都可以看作为一个进程,如打开的多个 word,就可以认为是一个进程的多个线程。

线程:至少有一个线程就是主线程,网络的异步请求就是多线程的应用。程序中我们写的代码段。单线程容易出现阻塞,程序的假死。多线程就不会出现这样的情况。

理解实例:一个餐厅的运营。餐厅的所有资源(电脑,菜,桌椅,地点,调料)的组合,就是一个程序的进程、(服务员,收银员,后厨)就是线程、程序的运行时靠线程(程序的代码块)的执行。

开辟子线程方式:

第一种:系统的写法

 NSThread * thread = [[NSThread alloc]initWithTarget:self selector:@selector(printf) object:nil];

    [thread start];//需要我们手动的开启线程,可以在程序的某些地方选择的开启线程

 第二种:自动的开启线程,调用一个自身的类方法

    [NSThread detachNewThreadSelector:@selector(printf) toTarget:self withObject:nil];

用户自己在程序的运行的某处要执行一个要执行很久的程序,但是不能让整个程序阻塞,就需要开辟一个线程。UI涮新,网络请求,点击事件是主线程要做的。

两种方法的区别,第一种必须手动的去调用。

栈区开辟的大小是1M主线程,我们自己开辟的子线程是512K,子线程是在主线程下执行。

(http://blog.csdn.net/echoisland/article/details/6403763 堆、栈、线程之间的关系)线程依赖于程序(进程),进程运行时内存是独立分配的,多线程运行的时候是共享内存。多线程的意义在于,通过进程管理线程让程序的不同功能块能够同时的进行运行,提高程序的运行效率。进程是某个具有独立功能的程序在一个数据集合上的一次运行,进程是操作系统进行调度和资源分配的独立单位。线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位.线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),但是它可与同属一个进程的其他的线程共享进程所拥有的全部资源. 
一个线程可以创建和撤销另一个线程;同一个进程中的多个线程之间可以并发执行.

堆:分为局部堆 和全局堆,前者是进程所分配得到的内存空间,后者就是所有没有分配的内存空间,局部堆使用完毕后要归还给操做系统,不然就是内存泄露。

栈:是线程独有的,(在高级语言中)不需要在程序的运行期间进行释放,用于在程序的运行期间保护程序线程的运行状态和局部变量,在线程运行的时候进行初始化。

堆和栈的区别可以用如下的比喻来看出:
使用栈就象我们去饭馆里吃饭,只管点菜(发出申请)、付钱、和吃(使用),吃饱了就走,不必理会切菜、洗菜等准备工作和洗碗、刷锅等扫尾工作,他的好处是快捷,但是自由度小。
使用堆就象是自己动手做喜欢吃的菜肴,比较麻烦,但是比较符合自己的口味,而且自由度大。

《主要看API文档学习方法》

线程的优先级,threadPriority 返回值是double (0.0-1.0)之间,1.0就是最先执行的线程

研究系统的编码写法(对于分类、以及定义的方法)

所有的线程(主线程、子线程)都要有一个自动释放池,要及时的自动清理。

对于耗时的任务可以交给子线程,而界面的刷新界面上用户的交互,点击事件,必须有主线程来处理。子线程中系统是不会自动生成一个自动释放池,所以需要我们手动添加一个自动释放池

同步请求与异步请求忘记了?????

    //网络请求的知识回顾

    NSString * str = @"";

    NSURL * Url = [NSURL URLWithString:str];

    NSURLRequest * request = [NSURLRequest requestWithURL:Url];

    // NSURLConnection 可以发起同步的,异步的请求

    NSData * data =[NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];//发起一个同步请求

    UIImage * image = [UIImage imageWithData:data];

系统的多线程的开辟方法

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
     
    //创建线程的第一种方式
    NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(run:) object:@"universe"];
    [thread start];
    [thread release];
     
     
    //创建线程的第二种方式,NSThread类方法
    [NSThread detachNewThreadSelector:@selector(run:) toTarget:self withObject:@"yuzhou"];
     
     
    //创建线程的第三种方法  NSObject方法
    [self performSelectorInBackground:@selector(run:) withObject:@"nsobject thread"];
     
    //创建线程的第四种方式
    NSOperationQueue *oprationQueue = [[NSOperationQueue alloc] init];
    [oprationQueue addOperationWithBlock:^{
        //这个block语句块在子线程中执行
        NSLog(@"oprationQueue");
    }];
    [oprationQueue release];
     
    //第五种创建线程的方式
    NSOperationQueue *oprationQueue1 = [[NSOperationQueue alloc] init];
    oprationQueue1.maxConcurrentOperationCount = 1;//指定池子的并发数
     
    //NSOperation 相当于java中的runnable接口,继承自它的就相当一个任务
    NSInvocationOperation *invation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(run:) object:@"invation"];
    [oprationQueue1 addOperation:invation];//将任务添加到池子里面,可以给池子添加多个任务,并且指定它的并发数
    [invation release];
     
    //第二个任务
    NSInvocationOperation *invation2 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(run2:) object:@"invocation2"];
    invation2.queuePriority = NSOperationQueuePriorityHigh;//设置线程优先级
    [oprationQueue1 addOperation:invation2];
    [invation2 release];
     
    [oprationQueue1 release];
     
    //调用主线程,用来子线程和主线程交互,最后面的那个boolean参数,如果为yes就是等这个方法执行完了在执行后面的代码;如果为no的话,就是不管这个方法执行完了没有,接着往下走
    [self performSelectorOnMainThread:@selector(onMain) withObject:self waitUntilDone:YES];
     
    //---------------------GCD----------------------支持多核,高效率的多线程技术
    //创建多线程第六种方式
    dispatch_queue_t queue = dispatch_queue_create("name", NULL);
    //创建一个子线程
    dispatch_async(queue, ^{
        // 子线程code... ..
        NSLog(@"GCD多线程");
         
        //回到主线程
        dispatch_sync(dispatch_get_main_queue(), ^{//其实这个也是在子线程中执行的,只是把它放到了主线程的队列中
            Boolean isMain = [NSThread isMainThread];
            if (isMain) {
                NSLog(@"GCD主线程");
            }
        });
    });
     
     
    self.window.backgroundColor = [UIColor whiteColor];
    [self.window makeKeyAndVisible];
    return YES;
}
 
- (void)onMain
{
    Boolean b = [NSThread isMainThread];
    if (b) {
        NSLog(@"onMain;;%d",b);
    }
}
 
 
- (void) run:(NSString*)str
{
    NSLog(@"多线程运行:::%@",str);
}
- (void) run2:(NSString*)str
{
    NSLog(@"多线程运行:::%@",str);
}
View Code 多线程的创建的几种方法
- (void)viewDidLoad {

    [super viewDidLoad];

    NSThread * thread = [[NSThread alloc] initWithTarget:self selector:@selector(handle1:) object:@"init创建"];

    [thread start];

    [NSThread detachNewThreadSelector:@selector(handle2:) toTarget:self withObject:@"detachNewThreadSelector方法创键"];

    [self performSelectorInBackground:@selector(handle:) withObject:@"后台创建的线程"];

    [self performSelector:@selector(handle:) withObject:self withObject:@"主线程创建子线程"];

    NSInvocationOperation * op1 = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(handle:) object:@"op1"];

    NSInvocationOperation * op2 = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(handle:) object:@"op2"];

    NSBlockOperation * op3 = [NSBlockOperation blockOperationWithBlock:^{

        NSLog(@"我是Block方法创键");

    }];

    NSOperationQueue * queue = [[NSOperationQueue alloc]init];

    [op1 addDependency:op3];

    [op2 addDependency:op3];

    

    [queue addOperation:op1];

    [queue addOperation:op2];

    [queue addOperation:op3];

    

}

 

-(void)handle2:(NSString *)str{

    NSLog(@"%@",str);

    [self performSelectorOnMainThread:@selector(handle:) withObject:@"由子线程返回主线程" waitUntilDone:YES];

}

-(void)handle1:(NSString *)str{

    NSLog(@"%@",str);

}

-(void)handle:(NSString *)str{

    NSLog(@"%@",str);

 }

 
View Code 多线程的创建方法

创建一个storyBoard文件,然后关联相关的类,下面代码出现的 Button 都是与它相关联的控件。

#pragma mark (.h文件)--------------------------------------------------------------------------------------------------------


#pragma mark (.m文件)--------------------------------------------------------------------------------------------------------

#import "AppDelegate.h"

@interface AppDelegate ()

@end

@implementation AppDelegate


- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
//    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
//    // Override point for customization after application launch.
//    self.window.backgroundColor = [UIColor whiteColor];
//    [self.window makeKeyAndVisible];
    return YES;
}
View Code Appdelegate文件
#pragma mark (.h文件)--------------------------------------------------------------------------------------------------------


#import <UIKit/UIKit.h>

@interface ViewController : UIViewController
/*CGD :苹果自己开发的处理多线程技术,优化用于程序,支持多核处理器和其他的多核处理系统。
 GCD:是函数级的多线程。采用C语言的函数,因为性能更高,功能更加强大
 */
@end


#pragma mark (.m文件)--------------------------------------------------------------------------------------------------------

#import "ViewController.h"

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}
//串行队列
- (IBAction)chuanxing:(id)sender {
    //1.获取一个串行操作队列
    //GCD自己封装的函数 获取程序主队列,他在系统的主线程中操作(也可自己创建一个队列,自己创建的对列在子线程中操作)
//    dispatch_queue_t queue1 = dispatch_get_main_queue();
//    //2.往队列里添加异步任务(带 a 的) (任务有 同步 异步之分)
//    dispatch_async(queue1, ^{
//        NSLog(@"任务1 %@",[NSThread currentThread]);
//    });
//    dispatch_async(queue1, ^{
//        NSLog(@"任务2 %@",[NSThread currentThread]);
//    });
    
    //自己创建的操作任务对列 他在系统的子线程中完成任务 线程同步(每次只能完成一个任务,故这里只创建一个子线程)
    //第一个参数:对列的名字 (命名的规范: 反域名的形式)
    //第二个参数:队列的属性 属性类型有两种(串行对列、并行队列)
    dispatch_queue_t queue2 =  dispatch_queue_create("com.lanou.hand", DISPATCH_QUEUE_SERIAL);
    //同步任务
    dispatch_sync(queue2, ^{
        NSLog(@"任务3 %@",[NSThread currentThread]);
    });
    dispatch_sync(queue2, ^{
        NSLog(@"任务4 %@",[NSThread currentThread]);
    });
    //对于同步任务不管是在那种类型的对列中他都是在主线程中完成,与异步任务的区别,如果放的是自己创建的队列,他就是在子线程中完成,如果是系统创建的对列则是在主线成中完成

}
//并行队列
- (IBAction)bingxingduilei:(id)sender {
    //线程并发,多个任务同时执行
    //获取队列  并发队列可以同时执行
    //使用系统创键好的
    //参数 第一个参数;队列的优先级   第二个参数:预留参数 给0
    dispatch_queue_t queue1 = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);//创建的是全局的并发线程
    //往对列中添加异步任务
    dispatch_async(queue1, ^{
        NSLog(@"任务1 %@",[NSThread currentThread]);
    });
    dispatch_async(queue1, ^{
        NSLog(@"任务2 %@",[NSThread currentThread]);
    });
    
//    //自己创建队列
//    dispatch_queue_t queue2 = dispatch_queue_create("com.lanou.39", DISPATCH_QUEUE_CONCURRENT);
//    dispatch_async(queue2, ^{
//        NSLog(@"任务3 %@",[NSThread currentThread]);
//    });
//    dispatch_async(queue2, ^{
//        NSLog(@"任务4 %@",[NSThread currentThread]);
//    });
    
    //获取主线程,由子线程进入到主线程,然后进行数据刷新
    dispatch_async(dispatch_get_main_queue(), ^{
        //
        NSLog(@"主线程刷新UI等等的操作");
        [self refreashUI];
    });
}

-(void)refreashUI{
    NSLog(@"刷新UI页面");
}
//分组
- (IBAction)fenzu:(id)sender {
    //分组使用的线程 用在 下载大容量视频。
    //1.创建一个并发队列  可以同时执行好多的任务
    dispatch_queue_t queue1 = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    //2.需要一个分组,创建一个分组
    dispatch_group_t  group1 = dispatch_group_create();
    //3.往队列中添加同一分组的异步任务
    //参数1 :分组    参数2 :任务队列  参数3: 添加任务等操作
    dispatch_group_async(group1, queue1, ^{
        NSLog(@"任务1<请求下载数据 0 - 20 > %@",[NSThread currentThread]);
    });
    dispatch_group_async(group1, queue1, ^{
        NSLog(@"任务2<请求下载数据 20 - 40 > %@",[NSThread currentThread]);
    });
    //4.在分组内的任务完成之后,触发该方法
    dispatch_group_notify(group1, queue1, ^{
        NSLog(@"任务3<请求拼接数据 > %@",[NSThread currentThread]);
    });
    //由子线程返回主线程
   dispatch_async(dispatch_get_main_queue(), ^{
       [self refreashUI];
   });

}

//一次
- (IBAction)onece:(id)sender {
    //代码只执行一次的方法
    //创建出一个 dispatch_once_t 对象
   static dispatch_once_t onceToken;//静态变量不给数据的时候,默认初始化为0
    dispatch_once(&onceToken, ^{
        //这里的代码只执行一次,单例的创建就可以写在这里
        NSLog(@"这里的代码只执行一次");
    });
}

//重复
- (IBAction)chongfu:(id)sender {
    //执行多次的代码
    //1.创建一个队列
    dispatch_queue_t queue1 = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    //添加重复的任务
    //参数1:参数重复的次数
    //参数2:任务队列
    //参数3:当前任务执行到的次数
    dispatch_apply(5, queue1, ^(size_t index) {//这里的Block 的写法,参数的名字是自己给的
        NSLog(@"%ld",index);//并发操作,得到一组数据不一定是规整的顺序
    });
}

//障碍
- (IBAction)zhangai:(id)sender {
    //障碍就是
    //1.获取并发(并行)队列。在使用障碍的时候,必须使用自己创键的队列
    //参数1:队列的唯一标示符号(不要加@)   参数2:对列的类型参数
    dispatch_queue_t queue1 = dispatch_queue_create("com.lanou.39", DISPATCH_QUEUE_CONCURRENT);
    //2.网队列里添加异步任务,(如果是同步任务就是一个一个的加)
    dispatch_async(queue1, ^{
        NSLog(@"A写入文件");
    });
    dispatch_async(queue1, ^{
        NSLog(@"B写入文件");
    });
    dispatch_async(queue1, ^{
        NSLog(@"C写入文件");
    });
    //添加阻碍(保证文件写入之后再读取文件)
    dispatch_barrier_async(queue1, ^{
        NSLog(@"添加阻碍(保证文件写入之后再读取文件)");
    });
    dispatch_async(queue1, ^{
        NSLog(@"读取文件A");
    });
    dispatch_async(queue1, ^{
        NSLog(@"读取文件B");
    });
    dispatch_async(queue1, ^{
        NSLog(@"读取文件B");
    });
}

//延迟
- (IBAction)yanchi:(id)sender {
    //获取一个并发异步队列
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    //添加延迟任务
    //参数1:延迟时间参数
    //参数2:任务队列
    //参数3:需要执行的代码
    //5秒钟之后在执行
    //int64_t 秒——时间类型
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0*NSEC_PER_SEC)), queue, ^{
        NSLog(@"延迟2秒后执行");
    });
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0*NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        NSLog(@"在主线程中延迟后2秒的时候执行");
    });
    //DISPATCH_TIME_FOREVER 就是永远也不执行的
//    dispatch_after(dispatch_time(DISPATCH_TIME_FOREVER, (int64_t)(2.0*NSEC_PER_SEC)), queue, ^{
//        NSLog(@"延迟2秒后执行");
//    });
}
@end
View Code ViewController文件

代码

没有创建可视化编程的控件。所有的内容都在控制台输出

#pragma mark (.h文件)--------------------------------------------------------------------------------------------------------


#import <UIKit/UIKit.h>

@interface ViewController : UIViewController
@property (weak, nonatomic) IBOutlet UIButton *but1;
@property (weak, nonatomic) IBOutlet UIButton *but2;

@end

#pragma mark (.m文件)--------------------------------------------------------------------------------------------------------

#import "ViewController.h"

/*
 1.多线程的GCD 的效率是最高的,要好好掌握
 2.对象一般都定义成属性  retain 保证对对象拥有所有权,如果UITableView 的数据源定义的时候,定义成实例变量,就会刷不出页面数据。尽管其他的代码都很正确
 3.系统的写法 1.需要手动的开启线程,可把线程定义成属性,控制进程的开关
 4.线程的互斥问题,就是当一个线程在访问的一块资源的时候,另一个线程也要对这块资源进行访问。出现访问的冲突这就是线程的互斥,解决线程的互斥,可以为线程添加一个线程锁,当一个线程在访问资源的时候,把线程上锁,这样另一个线程就处于等待访问资源状态,当访问资源访问结束的时候,再把线程锁打开,这样就保证了另一个线程能够访问数据。
 5.线程死锁,在解决线程互斥问题的时候,我们在第一个线程访问资源的时候,为线程添加了线程锁,但是在访问完数据之后并没有为线程锁开锁,这样就造成了另一个线程不能访问资源的情况,这就是线程的死锁。
6.   [NSThread currentThread];获得当前的线程
     [NSThread isMainThread];获得主线程
 7.    NSThread * thread = [[NSThread alloc] initWithTarget:self selector:@selector(handle) object:self];系统开启子线程,他需要我们手动去开启线程
 */


@interface ViewController ()
{
    NSInteger totalTickets;//总票数   实例变量记录票数
}
@property(nonatomic,retain)NSLock * lock;
@end

@implementation ViewController
//按钮1
- (IBAction)but1:(id)sender {
    

#pragma mark---系统 init 方法
    //这种写法程序仍然只有一个线程就是程序的主线程,程序运行默认生成的线程
    NSLog(@"使用的线程是:%@",[NSThread currentThread]);
    //系统的写法 1.需要手动的开启线程,可把线程定义成属性,控制进程的开关
    NSThread * thread = [[NSThread alloc]initWithTarget:self selector:@selector(printf:) object:@"系统方法开启子线程"];
    [thread start];
#pragma mark---NSObject 方法创建线程
    //创建一个后台运行的子线程
    [self performSelectorInBackground:@selector(printf:) withObject:@"NSObject 的主线程调用子线程后台执行"];
    //在主线程去执行一个方法
    [self performSelector:@selector(handle ) withObject:self withObject:@"子线程传入参数,就是前面方法的参数"];
}

-(void)printf:(NSString *)str{
    @autoreleasepool {
        NSLog(@"%d %@ %@",[NSThread isMainThread],[NSThread currentThread],str);
    }
}
//按钮2
- (IBAction)but2:(id)sender {
#pragma mark----NSThread调用一个自身的类方法开启线程
    //自动的开启线程,调用一个自身的类方法,内部已经封装了一个子线程
    //withObject 就是 执行方法要传的参数
    [NSThread detachNewThreadSelector:@selector(printf:) toTarget:self withObject:@"123"];
    //下载图片的任务交给子线程来完成
    [self performSelectorInBackground:@selector(downLoadImage) withObject:nil];
}
//分段控件
- (IBAction)segment:(id)sender {
}
#pragma mark---页面加载出来要执行的函数
- (void)viewDidLoad {
    [super viewDidLoad];
    totalTickets = 50;
    self.lock =  [[NSLock alloc]init];//如果把这一句放到下面就会在控制台出现异常
    [self viewDidLoad2];
}

-(void)downLoadImage{
#pragma mark----网络请求的知识回顾
    /*
    NSString * str = @"";
    NSURL * Url = [NSURL URLWithString:str];
    NSURLRequest * request = [NSURLRequest requestWithURL:Url];
    // NSURLConnection 可以发起同步的,异步的请求
    NSData * data =[NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];//发起一个同步请求
    UIImage * image = [UIImage imageWithData:data];
    */
    @autoreleasepool {
        UIImage * image = [UIImage imageWithData:[NSData  dataWithContentsOfURL:[NSURL URLWithString:@"图片请求网址"]]];//内部封装的是一个同步的请求(思考内部封装的4个过程)
        //返回主线程,进行界面的刷新操作
        [self performSelectorOnMainThread:@selector(refreashUI:) withObject:image waitUntilDone:YES];
        //waitUntilDone 参数什么意思
        
#pragma mark----NSOperationQueue 操作线程队列
        //NSOperationQueue 操作队列,我们常使用他的子类,来具体的执行实际的任务,
        //实际任务是由 NSOperation 的子类(NSInvocationOperation ,NSBlockOperation)来是实现
        //任务1  NSInvocationOperation
        NSInvocationOperation * op1 = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(printf:) object:@"OP1任务"];
        //任务2
        NSInvocationOperation * op2 = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(downLoadImage) object:@"OP2任务"];
        //把上面的任务放到操作队列,任务对列会为队列中的任务合理的安排子线程去完成任务(并不是按照添加的顺序执行)
        NSOperationQueue * quene = [[NSOperationQueue alloc]init];
        [quene addOperation:op1];
        [quene addOperation:op2];
        
#pragma mark----NSBlockOperation 创键任务
        //任务1 NSBlockOperation 创键任务
        NSBlockOperation * op3 = [NSBlockOperation blockOperationWithBlock:^{
            NSLog(@"我是 NSBlockOperation 创建任务");
        }];
        //任务2
        NSBlockOperation * op4 = [NSBlockOperation blockOperationWithBlock:^{
            NSLog(@"我是 NSBlockOperation 创建任务");
        }];
        NSOperationQueue *  quene2 = [[NSOperationQueue alloc]init];
        [quene2 addOperation:op3];
        [quene2 addOperation:op4];
        //完成任务机制:例如我们有8 个子任务,所谓的合理安排就是,某个任务完成之后,操作队列就会把下一个没有执行的任务放到这一个已经完成任务的线程
        //设置线程的最大的并发数目(就是一起执行任务的数目,实行线程的同步也可一说成是并发),对于网络请求有同步 异步 对于线程有 并发(任务同一时间同时执行) 与 串行(一个任务完后才执行下一个任务)
//        quene2.maxConcurrentOperationCount = 1;//默认是 - 1就是不限制的意思
        //上面代码注释掉,任务的执行顺序与放的顺序无关
        //设置任务之间的依赖关系 比如:第二个任务必须依赖于第一个任务先完成 我们要位第二个任务添加一个依赖
        [op3 addDependency:op4];//op3必须依赖于 op4先完成
        
    }
}
//刷新界面主线程的操作任务:刷新UI,处理用户交互
-(void)refreashUI:(UIImage *)image{
    //可以去设置图片
}
- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    
}


/*
 买票系统
 */
-(void)viewDidLoad2{
    totalTickets = 50;//初始化票数 50 张
    //窗口1
    [self performSelectorInBackground:@selector(sellTicket:) withObject:@"小明"];
    
    //窗口2
    [self performSelectorInBackground:@selector(sellTicket:) withObject:@"小刚"];
}

-(void)sellTicket:(NSString *)name{
    @autoreleasepool {
        while (YES) {
        //加锁
        [self.lock lock];
            if (totalTickets > 0) {
                totalTickets--;
                NSLog(@"%@ 卖完了,现在剩余的票数是:%ld",name,totalTickets);
            }else{
                NSLog(@"%@ 卖完了",name);
                break;
            }
         [self.lock unlock];//解锁
    }
  }
}

@end
View Code ViewController文件

在一个程序中开辟的同步线程不能过多,过多容易造成假死,所以能用异步线程就用异步线程。

//串行队列

- (IBAction)chuanxingduilei:(id)sender {

    dispatch_queue_t queue1 = dispatch_queue_create("niu", DISPATCH_QUEUE_SERIAL);

    dispatch_sync(queue1, ^{

        self.imagView.backgroundColor = [UIColor redColor];

        isYes =YES;

        [self text:@"queue1"];

    });

//    dispatch_queue_t queue2 = dispatch_get_main_queue();

//    dispatch_sync(queue2, ^{

//        [self text:@"main thread"];

//    });

}

//并行队列

- (IBAction)bingxingduilei:(id)sender {

    dispatch_queue_t queue1 = dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT,0);

     dispatch_async(queue1, ^{

        [self text:@"bingxing"];

         isYes = NO;

    });

    dispatch_async(queue1, ^{

        [self text:@"bingxing"];

        isYes = YES;

    });

    dispatch_async(queue1, ^{

        [self text:@"bingxing"];

        isYes = NO;

    });

}

//分组

- (IBAction)group:(id)sender {

    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

    dispatch_group_t group = dispatch_group_create();

    dispatch_group_async(group, queue, ^{

        [self text:@"分组"];

    });

}

//重复

- (IBAction)chongfu:(id)sender {

    dispatch_queue_t queue =dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

    dispatch_apply(5, queue, ^(size_t index) {

        [self text:[NSString stringWithFormat:@"第%ld次",index]];

    });

}

//一次

- (IBAction)oncetime:(id)sender {

   static dispatch_once_t onceToken;

    dispatch_once(&onceToken, ^{

        [self text:@"only once"];

    });

}

//障碍

- (IBAction)zhangai:(id)sender {

    dispatch_queue_t queue = dispatch_queue_create("barrier", DISPATCH_QUEUE_CONCURRENT);

    dispatch_async(queue, ^{

        [self text:@"1写入文件"];

    });

    dispatch_async(queue, ^{

        [self text:@"2写入文件"];

    });

    dispatch_async(queue, ^{

        [self text:@"3写入文件"];

    });

    dispatch_barrier_async(queue, ^{

        [self text:@"添加障碍"];

    });

    dispatch_async(queue, ^{

        [self text:@"读文件1"];

    });

    dispatch_async(queue, ^{

        [self text:@"读文件2"];

    });

    dispatch_async(queue, ^{

        [self text:@"读文件3"];

    });

}

//延迟

- (IBAction)yanchi:(id)sender {

    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5.0*NSEC_PER_SEC)), queue , ^{

        [self text:@"延迟5秒后执行"];

    });

    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0*NSEC_PER_SEC)), dispatch_get_main_queue(), ^{

        [self text:@"在主线程中延迟后2秒的时候执行"];

    });

 }

原文地址:https://www.cnblogs.com/benpaobadaniu/p/4858247.html