iOS-多线程

一、多线程的初步理解

  • 进程: 一个具有一定独立功能的程序关于某个数据集合的一次运行活动,可以理解成一个正在运行中的应用程序。
  • 线程: 程序执行流的最小单元,线程是进程中的一个实体,程序的运行必须依靠一个线程才能运行,一个程序运行可以有单个线程, 也可以有多个线程。
  • 同步: 只能在当前线程按先后顺序依次执行,不开启新线程。
  • 异步: 可以在当前线程开启多个新线程执行,可不按顺序执行,开启新的线程。
  • 并发: 线程执行可以同时多条线程一起进行执行,没有先后顺序,用于耗时较长的线程操作。
  • 串行: 线程执行只能依次逐一先后有序的执行,前面的程序执行成后才能有后面的程序执行。
  • 主线程:程序开始运行的时候,系统自动为我们开启一个新的线程,这个线程称为主线程
  • 子线程:程序员手动开启的线程,程序运行结束后自动释放。
  • 队列: 装载线程任务的队形结构,可以添加线程在同一个队列运行,任务运行在主线程还是子线程有队列决定。

二、多线程的分类及优缺点

1. pthread

优点:可以跨平台使用,基于纯C语言的面向对象,能够适用于多种操作系统, 可移植性强。
缺点:靠近底层实现,难以理解且使用难道大,线程的生命周期需要程序员自己管理,通常不使用。
举例:在view did load里面写如下代码 ( 注:需导入头文件 #import)

  pthread_t  pthread;新建一个

// 第一个参数: 线程指针

// 第二个参数: 线程的一些属性

// 第三个参数: 函数指针, 用于执行方法

// 第四个参数: 线程中的传值

    pthread_create(&pthread, NULL, run, NULL);

方法实现 :

void *run(void *papa)

{

for (NSInteger i = 0; i < 100000; i ++) {

NSLog(@"%lu",i);

}

return NULL;

}

2.NSThread

  • 优点:基于OC的面向对象编程,简单易用
  • 缺点:线程的生命周期由程序员管理,偶尔使用
NSTHread *thread =[ [NSThread alloc] initWithTarget:self selector:@selector(run) objects:"thread"];

thread.name = "thread"

[thread start] // 开启线程

NSLog(@"%@",thread);  // 线程打印 

NSLog(@"%@",[NSThread mainThread]);  // 当前应用程序的主线程

NSLog(@"%@",[NSThread currentThread]); // 当前线程

NSLog(@"%d",[NSThread isMainThread]); // 判断是否为主线程

// 快捷创建NSThread线程的方法

[NSThread detachNewThreadSelector:@selector(haoshicaozuo) toTarget:self withObject:@"123"];

[self performSelectorInBackground:@selector(haoshicaozuo) withObject:@"123"];

3.NSOperation

简介:NSOperation是个抽象类,我们一般不使用它,一般使用它的子类NSInvocationOperation和NSBlockOperation, 如果他们单独使用,则都是在主线程下执行,只有和队列放在一起才在子线程执行。

a.NSInvocationOperation

NSInvocationOperation *firstOperation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(firstRun) object:nil];

- (void) firstRun{

NSlog("第一个NSInvocation线程")

}



NSInvocationOperation *secondOperation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(secondRun) object:nil];

- (void) secondRun{

NSlog("第二个NSInvocation线程")

}

b.NSBlockOperation

NSBlockOperation  *thirdOperation  = [NSBlockOperation blockOperationWithBlock:^{

NSlog("block线程")

}

}];


//  NSOperationQueue *queue = [NSOperationQueue mainQueue]; mainQueue代表主队列

NSOperationQueue *queue = [[NSOperationQueue alloc] init]; // alloc init 代表其他队列

NSOperationQueue的作⽤:NSOperation可以调⽤start⽅法来执⾏任务,但默认是同步执行的,

如果将NSOperation添加到NSOperationQueue(操作队列)中,系统会自动异步执行NSOperation

中的操作

添加操作到NSOperationQueue中,自动执行操作,自动开启线程

// 先加的先执行, 后加的后执行, 但是执行的时间不一定, 可能后执行的程序比先执行的先执行完

[queue addOperation:firstOperation];  // 将线程加入队列

[queue addOperation:secondOperation]; // 将线程加入队列

[queue addOperation:thirdOperation]; // 将线程加入队列

4. GCD

a.同步 + 主队列 (不具备开启线程的能力, 在当前的线程完成任务)

- (void)creatScyncSerial

{

// 创建串行队列

dispatch_queue_t queue = dispatch_queue_create("aaa.com.queue", DISPATCH_QUEUE_SERIAL);

dispatch_sync(queue, ^{

NSLog(@"1------%@",[NSThread currentThread]);  

});   // dispatch_sync为同步

dispatch_sync(queue, ^{

NSLog(@"2------%@",[NSThread currentThread]);

});

dispatch_sync(queue, ^{

NSLog(@"3------%@",[NSThread currentThread]);

});

}

注:NSlog出现不输出情况,因为同步串行出现相互等待的情况,程序无法运行

b.异步 + 串行队列(能开启线程, 任务一个一个执行)

- (void)creatAsyncSerial

{

dispatch_queue_t queue = dispatch_queue_create("aaa.com.queue", DISPATCH_QUEUE_SERIAL);

dispatch_async(queue, ^{

NSLog(@"4--------%@",[NSThread currentThread]);

}); // dispatch_async 为异步

dispatch_async(queue, ^{

NSLog(@"5--------%@",[NSThread currentThread]);

});

dispatch_async(queue, ^{

NSLog(@"6--------%@",[NSThread currentThread]);

});

}

c.同步 + 并发队列(不具备开启线程的能力, 无法并发)

- (void)creatSyncConcurrent

{

// 第一个参数: 队列的名字

// 第二个参数: 队列的类型

// 我们自己创建的并发队列

//    dispatch_queue_t queue = dispatch_queue_create("sb.2b.com", DISPATCH_QUEUE_CONCURRENT);

// 创建一个并发队列

// 获得全局的并发队列

// 第一个参数为一个优先级: 默认的就行

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

dispatch_sync(queue, ^{

NSLog(@"1-------%@",[NSThread currentThread]);    });

dispatch_sync(queue, ^{

NSLog(@"2------%@",[NSThread currentThread]);

});

dispatch_sync(queue, ^{

NSLog(@"3-------%@",[NSThread currentThread]);

});

}

d.异步 + 并发队列 (使用频率较高,具备开启子线程的能力, 并发执行)

- (void)creatAsncConcurrent

{

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

dispatch_async(queue, ^{

NSLog(@"1------%@",[NSThread currentThread]);

});

dispatch_async(queue, ^{

NSLog(@"2------%@",[NSThread currentThread]);

});

dispatch_async(queue, ^{ 

NSLog(@"3------%@",[NSThread currentThread]);

});

}

4.NSThreade的简单应用(saleTickets)

a.将线程和票数设置为属性

@property (nonatomic,strong)NSThread *firstThread; // A售票员

@property (nonatomic,strong)NSThread *secondThread; // B售票员

@property (nonatomic,strong)NSThread *thirdThread; // C售票员

@property (nonatomic,assign)NSInteger ticketCount; // 总票数

b.添加线程并开启

self.ticketCount = 100;  // 总票数 设为100

self.firstThread = [[NSThread alloc] initWithTarget:self selector:@selector(saleTicket) object:nil];

self.secondThread = [[NSThread alloc] initWithTarget:self selector:@selector(saleTicket) object:nil];

self.thirdThread = [[NSThread alloc] initWithTarget:self selector:@selector(saleTicket) object:nil];

触摸屏幕时开启子线程

- (void)touchesBegan:(NSSet*)touches withEvent:(UIEvent *)event

{

[self.firstThread start];

[self.secondThread start];

[self.thirdThread start];

}

卖票的方法

- (void)saleTicket

{

while (1) {  // 设置1为死循环,未触发break时会一直运行卖票

// 线程锁 线程锁是唯一的, 只能有一把, 通常我们可以写上self, 加线程锁是防止三个线程同一时间卖票,当有一个线程开始卖票时,其他线程无法进行卖票。

@synchronized (self) {

//            NSLog(@"%@",self);

// 先取出总票数

NSInteger count = self.ticketCount;

if (count > 0) {

self.ticketCount = count - 1;

[NSThread sleepForTimeInterval:0.1];  // 线程暂停休息

NSLog(@"%@, %lu",[NSThread currentThread], self.ticketCount);

}else{

NSLog(@"票卖完了");

break;

           }

      }

}

你可能感兴趣的:(iOS-多线程)