码迷,mamicode.com
首页 > 编程语言 > 详细

多线程——NSThread、GCD、NSOperation

时间:2014-06-27 22:48:01      阅读:398      评论:0      收藏:0      [点我收藏+]

标签:style   blog   http   color   get   使用   

1、前言:

一个应用程序就是一个进程,一个进程至少包含一个线程,程序启动会自动创建一个主线程,负责UI界面的现实和控件事件的监控。多线程可以更充分的利用系统CPU资源,一定程度上提升程序的性能。1个进程可以开启多条线程,每条线程可以并行(同时)执行不同的任务。在一个线程内可以包含多个事物(要干的活),在线程内依据先进先出的特性串行执行……

2、NSThread

- (void)viewDidLoad
{
    [super viewDidLoad];
    NSLog(@"main thread is %@",[NSThread mainThread]);//打印主线程(UI线程)
}

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
    //新开辟一条子线程,启动子线程的时候调用downLoad方法,object是传递给子线程调用方法的参数
    NSThread *thread=[[NSThread alloc] initWithTarget:self selector:@selector(downLoad:) object:@"luseike"];
    //给子线程起一个名字
    thread.name=@"thread one";
    //开始子线程
    [thread start];
}

-(void)downLoad:(NSString *)param{
    //打印当前线程(子线程)及其名字和传递过来的参数
    NSLog(@"begin downLoad--param is %@--current thread is %@ current name is %@",param,[NSThread currentThread],[NSThread currentThread].name);
}

 打印结果如下:

2014-06-26 23:03:05.724 NSThread[50292:60b] main thread is <NSThread: 0x8c421c0>{name = (null), num = 1}

2014-06-26 23:03:06.567 NSThread[50292:3807] begin downLoad--param is luseike--current thread is <NSThread: 0xa33c350>{name = thread one, num = 2} current name is thread one

可以看到主线程的num=1,子线程的num=2,证明确实是新开辟了一条线程来执行downLoad操作。

还可以通过isMainThread判断是否是主线程,setThreadPriority:(double)p来设置子线程的优先级,优先级的取值范围在0.0~1.0之间,默认是0.5,值越大,优先级越高,被执行的几率越大

还有两种比较便捷的方式来创建子线程

1、[NSThread detachNewThreadSelector:@selector(downLoad:) toTarget:self withObject:@"luseike"];//  附加一个线程

2、[self performSelectorInBackground:@selector(downLoad:) withObject:@"haha"];  //在后台执行一个线程

这两种方式创建的子线程都不需要调用start方法,系统会自动执行对应的方法,都也都没有机会设置优先级和咸线程名等更详细的设置了,不过这个一般不重要

3、线程的状态

线程从生到死大致有下面几种状态:新建(new)、就绪(runnable)、运行(running)、阻塞(blocked)、死亡(dead)

一个线程被创建之后会放到一个叫做可调度线程池内,等待被CPU调度,当该线程获得CPU的执行权时,就进入到running状态。running状态的线程如果调用sleep方法或者在等待同步锁,就会进入阻塞状态,进入阻塞状态的线程会重新被放到可调度线程池内,等待被重新调度。线程任务执行完毕,或者被强制退出,会进入dead状态,注意:进入dead状态的线程并没有被释放内存,只是不能用了而已,还存在内存中。

bubuko.com,布布扣

 

4、控制线程的状态

启动线程:之前介绍过,调用start方法

阻塞(暂停)线程:

  + (void)sleepUntilDate:(NSDate *)date;

  + (void)sleepForTimeInterval:(NSTimeInterval)ti;

强制停止线程:+(void)exit;

多线程的安全隐患:当多个线程访问同一块资源时,很容易引发数据错乱和数据安全问题。解决的机制就是使用锁(互斥锁),让多条线程同步执行,这就是传说的线程同步技术。值得注意的是:锁定一份代码只用1把锁,用多把锁是没有意义的;线程同步的前提是多条线程抢占同一块资源

#import "ViewController.h"

@interface ViewController ()
@property(nonatomic,strong)NSThread *thread1;
@property(nonatomic,strong)NSThread *thread2;
@property(nonatomic,strong)NSThread *thread3;

@property(nonatomic,assign)int totalCount;
@end

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    self.totalCount=100;
    self.thread1=[[NSThread alloc] initWithTarget:self selector:@selector(saleTicket) object:nil];
    self.thread2=[[NSThread alloc] initWithTarget:self selector:@selector(saleTicket) object:nil];
    self.thread3=[[NSThread alloc] initWithTarget:self selector:@selector(saleTicket) object:nil];
}

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
    [self.thread1 start];
    [self.thread2 start];
    [self.thread3 start];
}

-(void)saleTicket{
    int leftCount=self.totalCount;
    while (leftCount>0) {
        self.totalCount=leftCount--;
        NSLog(@"%@ sale one ticket,left %d",[NSThread currentThread],leftCount);
    }
} @end

 如上代码,模拟3个子线程同时访问公共资源totalCount,每次操作减一,多线程访问同一资源容易引起的数据安全问题已经说明了,打印部分结果如下

2014-06-26 23:51:33.639 NSThread[63065:360b] <NSThread: 0xa06dd50>{name = (null), num = 3} sale one ticket,left 99

2014-06-26 23:51:33.639 NSThread[63065:3707] <NSThread: 0xa0706e0>{name = (null), num = 2} sale one ticket,left 99

2014-06-26 23:51:33.639 NSThread[63065:3f03] <NSThread: 0xa06ddf0>{name = (null), num = 4} sale one ticket,left 99

2014-06-26 23:51:33.641 NSThread[63065:3707] <NSThread: 0xa0706e0>{name = (null), num = 2} sale one ticket,left 98

2014-06-26 23:51:33.641 NSThread[63065:3f03] <NSThread: 0xa06ddf0>{name = (null), num = 4} sale one ticket,left 98

2014-06-26 23:51:33.642 NSThread[63065:3707] <NSThread: 0xa0706e0>{name = (null), num = 2} sale one ticket,left 97

2014-06-26 23:51:33.641 NSThread[63065:360b] <NSThread: 0xa06dd50>{name = (null), num = 3} sale one ticket,left 98

2014-06-26 23:51:33.642 NSThread[63065:3f03] <NSThread: 0xa06ddf0>{name = (null), num = 4} sale one ticket,left 97

可以看到三个子线程都操作了totalCount变量,每次操作之后的值却没有变化……

互斥锁的使用格式:

@synchronized(锁对象) { // 需要锁定的代码  }

-(void)saleTicket{
    while (1) {
        @synchronized(self) { // 加锁(只能用一把锁)
            // 1.先检查票数
            int count = self.totalCount;
            if (count > 0) {
                self.totalCount = count - 1;
                
                NSThread *current = [NSThread currentThread];
                NSLog(@"%@ sale one ticket, left %d tickets", current, self.totalCount);
            } else {
                [NSThread exit];
            }
        } 
    }
}

 打印结果就可以正常显示了……

很晚了,有时间在写写GCD和NSOperation

 

多线程——NSThread、GCD、NSOperation,布布扣,bubuko.com

多线程——NSThread、GCD、NSOperation

标签:style   blog   http   color   get   使用   

原文地址:http://www.cnblogs.com/luseike/p/3811128.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!