关于iOS多线程,你看我就够了(读)

原文地址:关于iOS多线程,你看我就够了 感谢博主的劳动,下面是对于原文的一些解读和测试


#import

void*start(void*data){

NSLog(@"pthread:%@",[NSThreadcurrentThread]);

returnNULL;

}

-(void)run:(NSString*)string{

NSLog(@"NSThread: %@",string);

NSThread* thread = [NSThreadcurrentThread];

NSLog(@"%@",[threadisMainThread]?@"MainThread":@"NotMainThread");

[threadcancel];

}

-(void)doSomething:(NSString*)string{

NSLog(@"doSomthings");

}



... //方法主体


NSLog(@"start testing =========================");

//Pthreads

/*

POSIX threads,简称Pthreads,是线程的POSIX标准。在类UINX操作系统(UNIX、Linux、MacOS X等)中都使用Pthreads作为操作系统的线程。基于c语言实现,移植性很强。但是比较蛋疼的是需要手动处理线程的各种状态的转换,管理生命周期。

*/

pthread_tthread0;

pthread_create(&thread0,NULL,start,NULL);

pthread_kill(thread0,0);

//NSThread

/*

经过apple封装的面向对象的线程方法。但是它的生命周期也需要手动管理。

Question1:如何确定@selector(run:),run的参数类型呢?

Question2:体会void *start(void *data)和-(void)run:(NSString*)string这两种函数定义的区别~~

*/

/*

NSDateFormatter* formatter = [[NSDateFormatter alloc]init];

[formatter setDateFormat:@"MMM dd,yyyy,HH:mm:ss"];

NSDate* date0 = [formatter dateFromString:@"12 12,1989,12:03:12"];

NSDate* date1 = [formatter dateFromString:@"12 12,1989,12:03:22"];

NSTimeInterval interval = [date0 timeIntervalSinceDate:date1];

*/

//挂起主线程,单位是秒

[NSThreadsleepForTimeInterval:1];

NSThread*thread1 = [[NSThreadalloc]initWithTarget:selfselector:@selector(run:)object:nil];

[thread1setName:@"Luke"];

[thread1start];

// [thread1 cancel];

//GCD:Grand Central Dispatch

/*

它是apple为多核的并行运算提出的解决方案,会自动合理的利用更多CPU内核,会自动管理线程的生命周期。

它也是用c语言的,但是因为使用了block,使用起来更方便。

主要有任务和队列两个概念。

任务:同步执行(sync)和异步执行(async)(Synchronized Asynchronous)

同步任务和异步任务的主要区别在于会不会阻塞当前线程,直到block执行完毕。sync会阻塞当前线程直到block执行完毕,线程才会继续执行。而async操作时,当前线程会继续执行。

队列:用于存放任务。一共有两种队列,串行队列和并行队列。

放到串行队列中的任务,GCD会按照FIFO(先进先出)依次取出一个一个执行。放到并行队列中的任务,GCD也会按照FIFO顺序取出,但是他取出后就会放入到一个新的线程中执行,因为取出时间几乎可以忽略,所以看起来并行队列中的任务是同时开始执行的。但是,GCD会根据系统资源控制并行的数量,所以如果任务很多时,并不能保证所有任务都同时执行。

*/

dispatch_queue_tqueue0 =dispatch_get_main_queue();//主线程队列,并行还是串行呢?????推测应该是并行

dispatch_queue_tqueue1 =dispatch_queue_create("threadsTest.dispatch.syncQueue1",NULL);//注意是""而非是@"",因为是c语言

dispatch_queue_tqueue2 =dispatch_queue_create("threadsTest.dispatch.syncQueue2",DISPATCH_QUEUE_SERIAL);//null和DISPATCH_QUEUE_SERIAL表示串行队列

dispatch_queue_tqueue3 =dispatch_queue_create("threadsTest.dispatch.asyncQueue3",DISPATCH_QUEUE_CONCURRENT);//并行队列

dispatch_queue_tqueue4 =dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0);//全局并行队列,并行任务一般都是加入到这个队列的。(应该是不会阻塞主线程的)

NSLog(@"before sync");

//dispatch_sync(queue0, ^{//引发问题的写法

dispatch_sync(queue1, ^{

//NSLog(@"sync %@",[NSThread currentThread]);

NSLog(@"done sync");

//return; //没有用,并不能结束这个串行线程

//这里的问题是,sync把主线程挂起后,自己没有结束,所以导致block和后面的内容都不会执行了。因为主线程队列中已经有了主线程,所以block会用主线程来执行,所以主线程挂起后,几乎什么事情都没有做了。而且GCD没有提供显式结束串行任务的api,所以导致无法退出挂起,所以串行任务应该加在非主线程队列中。

//加入非主线程队列中的逻辑是,挂起了非主线程队列中的其他线程,然后通过主线程执行block,执行完毕后唤醒非主线程队列中的其他线程

});//同步任务

NSLog(@"after sync");

NSLog(@"async 0");

dispatch_async(queue2, ^{//这里是正常的,往同步队列中放一个异步任务,会先建立一个线程执行,各走各的,使用当前异步线程执行block正常执行

NSLog(@"async 1");

//dispatch_sync(queue2, ^{//往同步队列中加入一个同步任务,因为是同步队列,已有有一个线程了,执行任务依托于原线程,挂起同步队列中其他所有的线程,也把异步线程挂起了,但是这里执行block需要用异步线程,因为线程挂起了,所以卡在这里了

dispatch_sync(queue0, ^{//放到主线程中,异步线程的任务正常执行

NSLog(@"async sync 2");

});

NSLog(@"async 3");

});

NSLog(@"async 4");

//上面这里例子核心要理解的是,执行任务是需要线程的,同步队列如果队列中已经有线程,应该就不会创建新的线程,所以一旦出现线程挂起,就会阻塞。主线程队列中自动就有一个线程,所以不会额外创建新的线程。新建线程队列的话,首先会先创建一个线程。

dispatch_sync(queue4, ^{

NSLog(@"tssss");//这里因为加入的是异步队列,所以会创建一个新的线程来执行任务,即便阻塞主线程,任务也能顺利结束。

});

NSLog(@"tasks end ");

//队列组,把所有队列放到一个队列组里,这样在所有任务执行完时,队列组可以通过一个方法来通知我们

dispatch_group_tgroup =dispatch_group_create();

dispatch_group_notify(group,dispatch_get_main_queue(), ^{

NSLog(@"when nothings");

});

//其实看到这里就知道,对于GCD理解是需要注意的是,考虑清楚任务也就是block是由哪个线程来执行的(因为所有任务的执行都依托于线程),而且什么时候回创建新线程

//NSOperation和NSOperationQueue

/*

NSOperation只是一个抽象类(c or c++概念),不能封装任务,但是它的两个子类,NSInvocationOperation和NSBlockOperation可以封装任务.它相较于GCD的好处应该在于可以取消中途任务

*/

NSInvocationOperation* opration = [[NSInvocationOperationalloc]initWithTarget:selfselector:@selector(doSomething:)object:nil];

// [opration start];

NSBlockOperation* blockOperation = [NSBlockOperationblockOperationWithBlock:^{

NSLog(@"block %@",[NSThreadcurrentThread]);

}];

for(inti =0; i <5; i++) {

[blockOperationaddExecutionBlock:^{//并发,会利用空闲线程(比如主线程)或者创建新线程执行。

NSLog(@"第%d次额外添加:%@",i,[NSThreadcurrentThread]);

if( i ==4){

[blockOperationcancel];

}

}];

}

[blockOperationstart];

NSOperationQueue* operationQueue = [NSOperationQueuemainQueue];

[operationQueueaddOperation:opration];//自动调用start

[operationQueuesetMaxConcurrentOperationCount:1];//这样就成同步队列了

//添加依赖

NSBlockOperation* b1 = [NSBlockOperationblockOperationWithBlock:^{

NSLog(@"block 1");

[NSThreadsleepForTimeInterval:1.];

}];

NSBlockOperation* b2 = [NSBlockOperationblockOperationWithBlock:^{

NSLog(@"block 2");

[NSThreadsleepForTimeInterval:2.];

}];

NSBlockOperation* b3 = [NSBlockOperationblockOperationWithBlock:^{

NSLog(@"block 3");

[NSThreadsleepForTimeInterval:1.0];

}];

[b2addDependency:b1];

[b3addDependency:b2];

//[b1 start];

//[b2 start];

//[b3 start];//start下依赖状态也正常

NSOperationQueue* bqueue = [[NSOperationQueuealloc]init];

[bqueueaddOperations:@[b1,b2,b3]waitUntilFinished:NO];

//线程同步问题

//互斥锁,保证一次只有一个线程访问这个代码块

@synchronized(self) {

NSLog(@"aaa");

}

//同步执行,串行队列就可以搞定

//延迟执行

[selfperformSelector:@selector(run:)withObject:@"abc"afterDelay:3.];

//GCD有dispatch_after

dispatch_after(dispatch_time(DISPATCH_TIME_NOW,10),dispatch_get_main_queue(), ^{

NSLog(@"主线程延迟10秒");

});

NSLog(@"dispatch_after是否会挂指定队列其他线程呢?答案是不会");

//NSTimer

[NSTimerscheduledTimerWithTimeInterval:10target:selfselector:@selector(run:)userInfo:@"efg"repeats:NO];

你可能感兴趣的:(关于iOS多线程,你看我就够了(读))