线程:

时间:线程在时间上可以分为“串行” 和“并发”两种方式,同步就是让我们的线程同时执行,异步线程不同时执行。强调时间性。

关系:线程在线程之间关系上可以分为“顺序执行”和“并行执行”,强调的是线程之间的关系。

任务:同步(Sync)和 异步(Async)(任务:就是执行操作,就是代码的运行)

同步(Sync)

  • 同步添加任务到指定的队列中,在添加的任务执行结束之前,会一直等待,直到队列里面的任务完成之后再执行
  • 只能在当前线程中执行任务,不具备开启新线程的能力

异步(Async)

  • 异步添加任务到指定的队列中,它不会做任何等待,可以继续执行任务
  • 可以在新的线程中执行任务,具备开启新线程的能力

队列 :串行和并行。

串行和并行

  • 相同: 串行队列和并发队列都符合先进先出的原则。
  • 区别: 执行的顺序不同,以及开启的线程数不同

四种组合情况(GCD为例)


- (void)viewDidLoad {
[super viewDidLoad];

    //1.获取并行队列,异步追加任务
    //[self concurrentAndAsync];

    //2.获取并行队列,同步追加任务
    //[self concurrentAndSync];

    //3.创建串行队列,异步追加任务
    //[self serialAndAsync];

    //4.创建串行队列,同步追加任务
    //[self serialAndSync];

    //5.向主队列中同步追加任务引起死锁
    [self addSyncTaskToMainQueue];

    [self mainQueuePrintTask];

}

1.获取并行队列,异步追加任务


- (void)concurrentAndAsync {

    //(1)获取全局队列
    dispatch_queue_t queue = dispatch_get_global_queue(
        DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

    //(2)开启多线程1:添加任务1
    dispatch_async(queue, ^{
        for (int i = 0; i < 20;i++) {
            NSLog(@"多线程1:%i", i);
        }
    });

    //(3)开启多线程2:添加任务2
    dispatch_async(queue, ^{
        for (int i = 0; i < 20;i++) {
            NSLog(@"多线程2:%i", i);
        }
    });

    //睡眠
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW,
        (int64_t)(2.0 * NSEC_PER_SEC)), queue, ^{
        NSLog(@"-------------等待2秒");
        // 2秒后异步执行这里的代码...
        [self postNoti];
        NSLog(@"-------------time");
    });

}

//打印结果: 主线程和多线程 之间没有任何先后顺序 同时执行
//打印结果: 主线程1和多线程2 之间也没有任何先后顺序 并发执行

2.获取并行队列,同步追加任务


- (void)concurrentAndSync {

    //(1)获取全局队列
    dispatch_queue_t queue = dispatch_get_global_queue(
        DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

    //(2)添加任务1
    dispatch_sync(queue, ^{
        for (int i = 0; i < 20;i++) {
            NSLog(@"任务1:%i", i);
        }
    });

    //(3)添加任务2
    dispatch_sync(queue, ^{
        for (int i = 0; i < 20;i++) {
            NSLog(@"任务2:%i", i);
        }
    });

}

//打印结果: 多线程在前 优先执行,多线程完成之后,主线程才执行
//打印结果: 多线程之中任务1在前 先执行 任务1完成之后,才执行任务2

3.创建串行队列,异步追加任务



- (void)serialAndAsync {
//(1)创建串行队列
dispatch_queue_t queue = dispatch_queue_create("iOS", DISPATCH_QUEUE_SERIAL);

    //(2)添加任务1
    dispatch_async(queue, ^{
        for (int i = 0; i < 20;i++) {
            NSLog(@"串行队列中执行任务1:%i", i);
        }
    });

    //(3)添加任务2
    dispatch_async(queue, ^{
        for (int i = 0; i < 20;i++) {
            NSLog(@"串行队列中执行任务2:%i", i);
        }
    });
}


//打印结果: 主线程和多线程 之间没有任何先后顺序 同时执行
//打印结果: 多线程之中任务1在前 先执行 任务1完成之后,才执行任务2

4.创建串行队列,同步追加任务



- (void)serialAndSync {
    //(1)创建串行队列
    dispatch_queue_t queue = dispatch_queue_create("iOS", DISPATCH_QUEUE_SERIAL);

    //(2)添加任务1
    dispatch_sync(queue, ^{
        for (int i = 0; i < 20;i++) {
            NSLog(@"串行队列中执行任务1:%i", i);
        }
    });

    //(3)添加任务2
    dispatch_sync(queue, ^{
        for (int i = 0; i < 20;i++) {
            NSLog(@"串行队列中执行任务2:%i", i);
        }
    });
}


//打印结果: 多线程在前 优先执行,多线程完成之后,主线程才执行
//打印结果: 多线程之中任务1在前 先执行 任务1完成之后,才执行任务2

5.向主队列中同步追加任务引起死锁



- (void)serialAndSync {
    dispatch_queue_t mainQueue = dispatch_get_main_queue();

    dispatch_async(mainQueue, ^{
        //NSLog(@"主队列中添加此任务");
        for (int i =0; i < 50; i++) {
            NSLog(@"%i", i);
        }
    });
}


//打印结果: 只有mainQueuePrintTask方法的打印,没有本方法的打印

主线程方法


- (void)postNoti{

    NSLog(@"睡眠2秒");
}

- (void)mainQueuePrintTask {
    for (int i = 0; i < 50000;i++) {
        NSLog(@"主线程:%i", i);
    }
}


同步执行 + 串行队列:我们把任务分配一个个线程,每个线程的任务都在主线程中执行。

异步执行 + 串行队列:队列中的任务顺序执行:在子线程中执行,主线程继续,不会等待子线程执行完毕。

同步执行 + 并发队列:(一般不用):队列中任务顺序执行,在主线程中执行(并行)

异步执行 + 并发队列:队列中的任务同时执行;在子线程中执行;主线程继续执行,不会等待子线程执行完毕。

NSThread的使用

1.优点:NSThread比其他两种多线程方案较轻量级,更直观地控制线程对象

2.缺点:需要自己管理线程的生命周期,线程同步。线程同步对数据的加锁会有一定的系统开销


- (void)viewDidLoad {
    [super viewDidLoad];


    //1.创建线程对象
    NSThread *thread = [[NSThread alloc] initWithTarget:self
        selector:@selector(thread) object:nil];
    thread.name = @"thread-2";
    // 设置线程的优先级(0.0 - 1.0,1.0最高级)
    thread.threadPriority = 1;
    //开启一个多线程
    [thread start];

    //2.创建一个线程对象,并且直接开启此线程,但无法获取线程对象。
    //[NSThread detachNewThreadSelector:@selector(thread)
        toTarget:self withObject:nil];


    //3.创建一个线程对象,并且启动此线程,调用当前self对象的方法。(隐式创建线程的方法)
    //[self performSelectorInBackground:@selector(thread) withObject:nil];
    //[self thread];
    
    for (int i = 0; i < 20; i++) {
        NSLog(@"主线程:%i",i);
    }

}

多线程的入口方法


- (void)thread {


    //获取当前方法的线程对象
    NSThread *thread = [NSThread currentThread];
    NSLog(@"thread-2:%@", thread);
    //获取主线程
    //NSThread *main = [NSThread mainThread];


    //多线程分配堆栈大小为512k
    NSLog(@"thread-2:stackSize:%li", [thread stackSize]);

    for (int i = 0; i < 50; i++) {

        if (i == 10) {

            NSLog(@"thread sleep");
            //使当前线程睡眠
            [NSThread sleepForTimeInterval:2];
        }

        if (i == 20) {
            NSLog(@"thread end");
            //线程退出
            [NSThread exit];
            }
            NSLog(@"thread:%i",i);
        }

        //判断当前线程是否为主线程
        if (![NSThread isMainThread]) {
            NSLog(@"当前线程不是主线程");
        }
    }

NSOperationQueue使用


- (void)viewDidLoad {
    [super viewDidLoad];


    //1.创建一个线程队列(线程池)
    NSOperationQueue *queue = [[NSOperationQueue alloc] init];

    //2.创建线程 //NSOperation->NSInvocationOperation
    NSInvocationOperation *op1 = [[NSInvocationOperation alloc] initWithTarget:self
    selector:@selector(thread1:) object:@"operation-1"];

    NSInvocationOperation *op2 = [[NSInvocationOperation alloc] initWithTarget:self
    selector:@selector(thread2:)object:@"operation-2"];

    HWOperation *op3 = [[HWOperation alloc] initTarget:self
    selector:@selector(thread3)];

    //设置queue的并发数
    //queue.maxConcurrentOperationCount = 1;

    op2.queuePriority = NSOperationQueuePriorityVeryHigh;

    //[queue setSuspended:YES];

    //3.把线程对象加入到线程队列中
    [queue addOperation:op1];
    [queue addOperation:op2];

    [queue addOperation:op3];

    //[queue setSuspended:NO];

    //[queue addOperationWithBlock:^{
    //    for (int i = 0; i < 20; i++) {
    //        NSLog(@"block:%i", i);
    //    }
    //}];

    for (int i = 0; i < 10; i++) {
        NSLog(@"主线程:%i",i);
    }

}

线程方法


//线程thread1入口方法
- (void)thread1:(NSString *)name {

    for (int i = 0; i < 20; i++) {
        NSLog(@"多线程%@:%i", name, i);
    }
}

//线程thread2入口方法
- (void)thread2:(NSString *)name {

    for (int i = 0; i < 20; i++) {
        NSLog(@"多线程%@:%i", name, i);
    }
}

//自定义线程类:thread3的入口方法
- (void)thread3 {
    for (int i = 0; i < 20; i++) {
        NSLog(@"HWOPeration线程:%i", i);
    }
}

只是简单使用,多有不足,有时间再补充吧