IOS开发,多线程,GDC ,线程 详解

NSRunLoop 循环机制

NSRunTime 循环时刻

什么时候创建子线程是有条件的

1.进行大量数据运算   for

数据库查询 select 将 select放在子线程中

2.网络请求 异步(将异步放在子线程中)

IOS中关于UI的添加必须在主线程中操作

子线程不能修改,创建跟UI相关的任何内容

想要修改,必须在主线程上

进程号 : 线程号

- (void)viewDidLoad

{

[super viewDidLoad];

// Do any additional setup after loading the view.

NSString *str = @"点击测试";

NSString *str1 = @"等运算结果吧,别急";

UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(50, 50, 75, 40)];

button.backgroundColor = [UIColor cyanColor];

[button setTitle:str forState:UIControlStateNormal];

[button setTitle:str1 forState:UIControlStateHighlighted];

[button addTarget:self action:@selector(buttonAction:) forControlEvents:UIControlEventTouchUpInside];

[self.view addSubview:button];

[button release];

}

- (void)buttonAction:(id)sender

{

unsigned long result = 0;

for (int i = 1; i < 635500000; i++) {

result = result+i;

NSLog(@"%lu", result);

}

}

NSThread 轻量级的多线程

- (void)viewDidLoad

{

[super viewDidLoad];

// Do any additional setup after loading the view.

NSString *str = @"点击测试";

NSString *str1 = @"等运算结果吧,别急";

UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(50, 50, 75, 40)];

button.backgroundColor = [UIColor cyanColor];

[button setTitle:str forState:UIControlStateNormal];

[button setTitle:str1 forState:UIControlStateHighlighted];

[button addTarget:self action:@selector(createThread:) forControlEvents:UIControlEventTouchUpInside];

[self.view addSubview:button];

[button release];

}

//NSThread方法创建子线程  这个只是告诉哪个方法在子线程中跑

- (void)createThread:(id)sender

{

//NSThread第一种写法

//    NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(threadAction) object:NULL];

//    [thread start];

//    [thread release];

//NSThread第二种写法

[NSThread detachNewThreadSelector:@selector(threadAction) toTarget:self withObject:NULL];

}

- (void)threadAction

{

//创建autoreleasepool方法一

//    @autoreleasepool {

//        unsigned long result = 0;

//        for (int i = 1; i < 635500000; i++) {

//            result = result+i;

//            NSLog(@"%lu", result);

//        }

//    }

//创建autoreleasepool  方法二  只能在MRC中 使用

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

//unsigned 无符号的意思  unsigned long 无符号长整形

unsigned long result = 0;

for (int i = 1; i < 635500000; i++) {

result = result+i;

NSLog(@"%lu", result);

}

[pool release];  //NSAutoreleasePool  释放池的第一种方法

//    [pool drain]      //NSAutoreleasePool  释放池的第二种方法

}

NSOperation

NSOperationQueue 称为线程队列

OperationQueue才是多线程

#pragma mark -

#pragma mark Operation创建子线程

#import "Operation.h"

.

.

.

.

.

.

- (void)createOperation

{

NSLog(@"%s",__func__);

Operation *operation = [[Operation alloc] init];

Operation *operation1 = [[Operation alloc] init];

Operation *operation2 = [[Operation alloc] init];

Operation *operation3 = [[Operation alloc] init];

Operation *operation4 = [[Operation alloc] init];

operation.delegate = self;

//    [operation start];

//下面这两行  等于start的功能    主要是看进程号,看进程号跟主线程的进程号是不是一样  来确定是否在主线程上

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

[queue setMaxConcurrentOperationCount:2];//限制子线程的最大并行数

[queue addOperation:operation];

[queue addOperation:operation1];

[queue addOperation:operation2];

[queue addOperation:operation3];

[queue addOperation:operation4];

[queue release];

//Operation 要和 OperationQueue  成对使用  单独使用没有用

//OperationQueue才是多线程  operation只是多线程中的一个方法

}

- (void)sendImage:(UIImage *)image

{

UIImageView *aImage = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 320, self.view.frame.size.height)];

aImage.image = image;

[self.view addSubview:aImage];

[aImage release];

}

#import

@protocol OperationDelegate;

@interface Operation : NSOperation

@property(nonatomic , assign) iddelegate;

@end

@protocol OperationDelegate

- (void)sendImage:(UIImage *)image;

@end

#import

@protocol OperationDelegate;

@interface Operation : NSOperation

@property(nonatomic , assign) iddelegate;

@end

@protocol OperationDelegate

- (void)sendImage:(UIImage *)image;

@end

#import "Operation.h"

@implementation Operation

- (void)dealloc

{

[super dealloc];

}

- (instancetype)init

{

self = [super init];

if (self) {

}

return self;

}

- (void)main

{

//    @autoreleasepool {

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

//        unsigned long result = 0;

//        for (int i = 1; i < 10; i++) {

//            result = result+i;

//            NSLog(@"%lu", result);

//        }

//    }

NSURL * url = [NSURL URLWithString:@" 图片网址(自己写,博客上不让发链接) "];

NSData *data = [NSData dataWithContentsOfURL:url];

UIImage *aImage = [UIImage imageWithData:data];

//判断代理人是否能够调用这个方法

if ([self.delegate respondsToSelector:@selector(sendImage:)]) {

//        [self.delegate sendImage:aImage];

[self performSelectorOnMainThread:@selector(finished:) withObject:aImage waitUntilDone:YES];

}

}

- (void)finished:(UIImage *)aimage

{

[self.delegate sendImage:aimage];

}

@end

NSObject 创建子线程

#pragma mark -

#pragma mark NSObject创建子线程

- (void)objectThread

{

[self performSelectorInBackground:@selector(threadAction) withObject:NULL];

}

NSthread

NSOperation

NSObject

以上三个是IOS4.0以前经常用的

他们返回主线程的方法就是用

[performSelectorInBackground: withObject: ]

________________________________________________________________________________________________________________________________

GCD(Grand Central Dispatch)

Grand Central Dispatch 简称(GCD)是苹果公司开发的技术,以优化应用程序支持多核心处理器和其他的对称多处理系统的系统。其建立在任务并行执行的线程池模式的基础上的。它首次发布在Mac OS X 10.6 ,iOS 4及以上也可用。

GCD工作原理

1. GCD让程序平行排队执行任务,根据可用的处理资源,安排他们在任何可用的处理器核心上执行任务。

2. 一个任务可以是一个函数(function)或者是一个block。 GCD的底层依然是用线程实现,不过这样可以让程序员不用关注实现的细节。

3. GCD中的FIFO队列称为dispatch queue,它可以保证先进来的任务先得到执行

dispatch queue分为下面三种:

Serial:

又称为private dispatch queues,同时只执行一个任务。Serial queue通常用于同步访问特定的资源或数据。当你创建多个Serial queue时,虽然它们各自是同步执行的,但Serial queue与Serial queue之间是并发执行的。

Concurrent:

又称为global dispatch queue,可以并发地执行多个任务,但是执行完成的顺序是随机的。

Main dispatch queue:

它是全局可用的serial queue,它是在应用程序主线程上执行任务的。

#import "MainViewController.h"

@interface MainViewController ()

@end

@implementation MainViewController

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil

{

self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];

if (self) {

// Custom initialization

}

return self;

}

- (void)viewDidLoad

{

[super viewDidLoad];

// Do any additional setup after loading the view.

}

#pragma mark -

#pragma mark 创建一个同步的线程队列

- (void)createSerailGCD

{

//@""  是NSString类型  " " 是char类型

//创建一个变量名为queue的线程队列,队列的名字叫"first",队列类型为 同步的.

dispatch_queue_t queue = dispatch_queue_create("first", DISPATCH_QUEUE_SERIAL);

//异步执行线程队列

dispatch_async(queue, ^{

//在多线程中执行的代码

NSURL * url = [NSURL URLWithString:@" 图片地址 "];

NSData *data = [NSData dataWithContentsOfURL:url];

UIImage *aImage = [UIImage imageWithData:data];

//异步返回主线程    dispatch_get_main_queue() 返回主线程的方法

dispatch_async(dispatch_get_main_queue(), ^{

UIImageView * imageView = [[UIImageView alloc] initWithImage:aImage];

[imageView release];

});

});

}

#pragma mark -

#pragma mark 创建一个并发的线程队列

- (void)createConcurrentGCD

{

//并发中,下面注释这段可以省略 用别的代替  上面跟下面的效果是一样的

//    dispatch_queue_t queue = dispatch_queue_create("second", DISPATCH_QUEUE_CONCURRENT);

//    dispatch_async(queue, ^{

//

//    });

//由这句话代表上面注释这段话  DISPATCH_QUEUE_PRIORITY_DEFAULT 默认的 级别高的先运行,级别低的后运行

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

//在多线程中执行的代码

NSURL * url = [NSURL URLWithString:@" 图片地址 "];

NSData *data = [NSData dataWithContentsOfURL:url];

UIImage *aImage = [UIImage imageWithData:data];

//异步返回主线程

dispatch_async(dispatch_get_main_queue(), ^{

UIImageView * imageView = [[UIImageView alloc] initWithImage:aImage];

[imageView release];

});

});

}

@end

返回主线程方法

返回主线程类型

方法:

GCD

dispatch_get_main_queue()

NSObject

- (void)performSelectorOnMainThread:(SEL)aSelector withObject:(id)arg waitUntilDone:(BOOL)wait

线程互斥场景

线程互斥是指某一资源同时只允许一个访问者对其进行访问,具有唯一性和排它性。但互斥无法限制访问者对资源的访问顺序,即访问是无序的。因此需要加上互斥锁来进行顺序访问,最具有代表性的就是买票系统!

条件锁

NSConditionLock称为条件锁,它的应用场景通常为线程同步。

当我们在使用多线程的时候,有时一把只会lock和unlock的锁未必就能完全满足我们的使用。因为普通的锁只能关心锁与不锁,而不在乎用什么钥匙才能开锁,而我们在处理资源共享的时候,多数情况是只有满足一定条件的情况下才能打开这把锁,比如生产者和消费者!

递归锁

NSRecursiveLock称为递归锁

平时我们在代码中使用锁的时候,最容易犯的一个错误就是造成死锁,而容易造成死锁的一种情形就是在递归或循环中。

NSRecursiveLock

在线程1中的递归block中,锁会被多次的lock,所以自己也被阻塞了,那么如何在递归或循环中正确的使用锁呢?此处的“锁”如果换用NSRecursiveLock对象,问题便得到解决了,NSRecursiveLock类定义的锁可以在同一线程多次lock,而不会造成死锁。递归锁会跟踪它被多少次lock。每次成功的lock都必须平衡调用unlock操作。只有所有的锁住和解锁操作都平衡的时候,锁才真正被释放给其他线程获得

你可能感兴趣的:(IOS开发,多线程,GDC ,线程 详解)