`

iOS多线程编程之NSThread的使用 .

    博客分类:
  • ios
阅读更多
1、简介:
1.1 iOS有三种多线程编程的技术,分别是:
1.、NSThread

2、Cocoa NSOperation (iOS多线程编程之NSOperation和NSOperationQueue的使用)

3、GCD  全称:Grand Central Dispatch( iOS多线程编程之Grand Central Dispatch(GCD)介绍和使用)

这三种编程方式从上到下,抽象度层次是从低到高的,抽象度越高的使用越简单,也是Apple最推荐使用的。

这篇我们主要介绍和使用NSThread,后面会继续2、3 的讲解和使用。

1.2 三种方式的有缺点介绍:
NSThread:

优点:NSThread 比其他两个轻量级

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

NSThread实现的技术有下面三种:

[img]

[/img]

一般使用cocoa thread 技术。




Cocoa operation

优点:不需要关心线程管理,数据同步的事情,可以把精力放在自己需要执行的操作上。

Cocoa operation 相关的类是 NSOperation ,NSOperationQueue。NSOperation是个抽象类,使用它必须用它的子类,可以实现它或者使用它定义好的两个子类:NSInvocationOperation 和 NSBlockOperation。创建NSOperation子类的对象,把对象添加到NSOperationQueue队列里执行。



GCD

Grand Central Dispatch (GCD)是Apple开发的一个多核编程的解决方法。在iOS4.0开始之后才能使用。GCD是一个替代诸如NSThread, NSOperationQueue, NSInvocationOperation等技术的很高效和强大的技术。现在的iOS系统都升级到6了,所以不用担心该技术不能使用。



介绍完这三种多线程编程方式,我们这篇先介绍NSThread的使用。

2、NSThread的使用
2.1 NSThread 有两种直接创建方式:
- (id)initWithTarget:(id)target selector:(SEL)selector object:(id)argument

+ (void)detachNewThreadSelector:(SEL)aSelector toTarget:(id)aTarget withObject:(id)anArgument

第一个是实例方法,第二个是类方法

1、[NSThread detachNewThreadSelector:@selector(doSomething:) toTarget:self withObject:nil];
2、NSThread* myThread = [[NSThread alloc] initWithTarget:self
                                        selector:@selector(doSomething:)
                                        object:nil];
[myThread start];



2.2参数的意义:

selector :线程执行的方法,这个selector只能有一个参数,而且不能有返回值。

target  :selector消息发送的对象

argument:传输给target的唯一参数,也可以是nil

第一种方式会直接创建线程并且开始运行线程,第二种方式是先创建线程对象,然后再运行线程操作,在运行线程操作前可以设置线程的优先级等线程信息



2.3 PS:不显式创建线程的方法:
用NSObject的类方法  performSelectorInBackground:withObject: 创建一个线程:
[Obj performSelectorInBackground:@selector(doSomething) withObject:nil];



2.4 下载图片的例子:
2.4.1  新建singeView app
新建项目,并在xib文件上放置一个imageView控件。按住control键拖到viewControll

er.h文件中创建imageView IBOutlet

ViewController.m中实现:

//
//  ViewController.m
//  NSThreadDemo
//
//  Created by rongfzh on 12-9-23.
//  Copyright (c) 2012年 rongfzh. All rights reserved.
//

#import "ViewController.h"
#define kURL @"http://avatar.csdn.net/2/C/D/1_totogo2010.jpg"
@interface ViewController ()

@end

@implementation ViewController

-(void)downloadImage:(NSString *) url{
    NSData *data = [[NSData alloc] initWithContentsOfURL:[NSURL URLWithString:url]];
    UIImage *image = [[UIImage alloc]initWithData:data];
    if(image == nil){
        
    }else{
        [self performSelectorOnMainThread:@selector(updateUI:) withObject:image waitUntilDone:YES];
    }
}

-(void)updateUI:(UIImage*) image{
    self.imageView.image = image;
}


- (void)viewDidLoad
{
    [super viewDidLoad];
    
//    [NSThread detachNewThreadSelector:@selector(downloadImage:) toTarget:self withObject:kURL];
    NSThread *thread = [[NSThread alloc]initWithTarget:self selector:@selector(downloadImage:) object:kURL];
    [thread start];
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

@end



2.4.2线程间通讯
线程下载完图片后怎么通知主线程更新界面呢?


[self performSelectorOnMainThread:@selector(updateUI:) withObject:image waitUntilDone:YES];

performSelectorOnMainThread是NSObject的方法,除了可以更新主线程的数据外,还可以更新其他线程的比如:
用:performSelector:onThread:withObject:waitUntilDone:

运行下载图片:

[img]

[/img]

图片下载下来了。








2.3 线程同步
我们演示一个经典的卖票的例子来讲NSThread的线程同步:

.h

#import <UIKit/UIKit.h>

@class ViewController;

@interface AppDelegate : UIResponder <UIApplicationDelegate>
{
    int tickets;
    int count;
    NSThread* ticketsThreadone;
    NSThread* ticketsThreadtwo;
    NSCondition* ticketsCondition;
    NSLock *theLock;
}
@property (strong, nonatomic) UIWindow *window;

@property (strong, nonatomic) ViewController *viewController;

@end



- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    
    tickets = 100;
    count = 0;
    theLock = [[NSLock alloc] init];
    // 锁对象
    ticketsCondition = [[NSCondition alloc] init];
    ticketsThreadone = [[NSThread alloc] initWithTarget:self selector:@selector(run) object:nil];
    [ticketsThreadone setName:@"Thread-1"];
    [ticketsThreadone start];
    
    
    ticketsThreadtwo = [[NSThread alloc] initWithTarget:self selector:@selector(run) object:nil];
    [ticketsThreadtwo setName:@"Thread-2"];
    [ticketsThreadtwo start];
    
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    // Override point for customization after application launch.
    self.viewController = [[ViewController alloc] initWithNibName:@"ViewController" bundle:nil];
    self.window.rootViewController = self.viewController;
    [self.window makeKeyAndVisible];
    return YES;
}

- (void)run{
    while (TRUE) {
        // 上锁
//        [ticketsCondition lock];
        [theLock lock];
        if(tickets >= 0){
            [NSThread sleepForTimeInterval:0.09];
            count = 100 - tickets;
            NSLog(@"当前票数是:%d,售出:%d,线程名:%@",tickets,count,[[NSThread currentThread] name]);
            tickets--;
        }else{
            break;
        }
        [theLock unlock];
//        [ticketsCondition unlock];
    }
}



如果没有线程同步的lock,卖票数可能是-1.加上lock之后线程同步保证了数据的正确性。
上面例子我使用了两种锁,一种NSCondition ,一种是:NSLock。 NSCondition我已经注释了。

线程的顺序执行
他们都可以通过

        [ticketsCondition signal]; 发送信号的方式,在一个线程唤醒另外一个线程的等待。

比如:

#import "AppDelegate.h"

#import "ViewController.h"

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    
    tickets = 100;
    count = 0;
    theLock = [[NSLock alloc] init];
    // 锁对象
    ticketsCondition = [[NSCondition alloc] init];
    ticketsThreadone = [[NSThread alloc] initWithTarget:self selector:@selector(run) object:nil];
    [ticketsThreadone setName:@"Thread-1"];
    [ticketsThreadone start];
    
    ticketsThreadtwo = [[NSThread alloc] initWithTarget:self selector:@selector(run) object:nil];
    [ticketsThreadtwo setName:@"Thread-2"];
    [ticketsThreadtwo start];
    
    NSThread *ticketsThreadthree = [[NSThread alloc] initWithTarget:self selector:@selector(run3) object:nil];
    [ticketsThreadthree setName:@"Thread-3"];
    [ticketsThreadthree start];    
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    // Override point for customization after application launch.
    self.viewController = [[ViewController alloc] initWithNibName:@"ViewController" bundle:nil];
    self.window.rootViewController = self.viewController;
    [self.window makeKeyAndVisible];
    return YES;
}

-(void)run3{
    while (YES) {
        [ticketsCondition lock];
        [NSThread sleepForTimeInterval:3];
        [ticketsCondition signal];
        [ticketsCondition unlock];
    }
}

- (void)run{
    while (TRUE) {
        // 上锁
        [ticketsCondition lock];
        [ticketsCondition wait];
        [theLock lock];
        if(tickets >= 0){
            [NSThread sleepForTimeInterval:0.09];
            count = 100 - tickets;
            NSLog(@"当前票数是:%d,售出:%d,线程名:%@",tickets,count,[[NSThread currentThread] name]);
            tickets--;
        }else{
            break;
        }
        [theLock unlock];
        [ticketsCondition unlock];
    }
}




wait是等待,我加了一个 线程3 去唤醒其他两个线程锁中的wait


其他同步
我们可以使用指令 @synchronized 来简化 NSLock的使用,这样我们就不必显示编写创建NSLock,加锁并解锁相关代码。
- (void)doSomeThing:(id)anObj
{
    @synchronized(anObj)
    {
        // Everything between the braces is protected by the @synchronized directive.
    }
}
还有其他的一些锁对象,比如:循环锁NSRecursiveLock,条件锁NSConditionLock,分布式锁NSDistributedLock等等,可以自己看官方文档学习





  • 大小: 88.6 KB
  • 大小: 151.4 KB
分享到:
评论

相关推荐

    iOS多线程开发NSThread.pdf

    iOS 多线程开发 NSThread 是 iOS 平台上支持的多线程编程方式之一。多线程编程是指一个应用程序同时执行多个线程,以提高应用程序的响应速度和效率。iOS 支持多个层次的多线程编程,层次越高的抽象程度越高,使用...

    iOS 多线程编程指南 pdf

    iOS多线程编程指南是一份深入介绍iOS平台下多线程编程技术的文档。文档主要涵盖的技术点包括NSThread、NSOperation以及Grand Central Dispatch(GCD),这些技术是iOS开发者在开发应用程序时常用的技术。 首先,...

    iOS多线程编程之NSThread的使用案例

    iOS多线程编程之NSThread的使用案例源码,1、简介:1.1 iOS有三种多线程编程的技术,分别是:1.、NSThread 。2、Cocoa NSOperation (iOS多线程编程之NSOperation和NSOperationQueue的使用)3、GCD 全称:Grand ...

    ios多线程编程

    iOS多线程编程是iOS开发中的一个重要技能,对于提升应用程序的性能和用户体验至关重要。在iOS平台上,多线程编程可以通过多种技术实现,包括NSThread、Grand Central Dispatch(GCD)、Operation Objects等。本文档...

    iOS多线程编程技术之NSThread、Cocoa NSOperation、GCD

    ### iOS多线程编程技术详解:NSThread、Cocoa NSOperation、GCD #### 一、多线程基本概念 1. **进程**:在移动设备(如iPhone)上,每一个应用程序都可以被视为一个独立的进程。每个进程都会有一个主线程(main ...

    iOS多线程编程指南(一)关于多线程编程 - 51CTO.COM1

    本文将作为iOS多线程编程指南的第一部分,深入探讨多线程的基本概念、常用技术以及最佳实践。 1. **多线程基础** 多线程是指在一个应用程序中同时执行多个独立的执行流,每个执行流被称为一个线程。在iOS中,多...

    ios 多线程编程指南

    以上就是iOS多线程编程指南的主要知识点,详细解读了多线程编程中的基本概念、线程管理技巧、RunLoop对象的使用以及线程同步工具等。开发者需要深入理解这些概念,并在实践中妥善应用,以实现高效的多线程编程。

    ios多线程开发的常用四种方式和基本使用

    本文将深入探讨四种常用的iOS多线程开发方式:pthread、NSThread、NSOperation及NSOperationQueue,以及Grand Central Dispatch(GCD)。 首先,让我们了解下pthread。pthread是POSIX线程库,它在iOS中被用于跨平台...

    IOS应用源码——ui多线程的简单例子 NSThread.zip

    这个名为"NSThread.zip"的压缩包提供了一个简单的iOS应用源码示例,专门用于演示如何在iOS中使用NSThread进行多线程编程。 首先,我们要理解什么是多线程。在计算机系统中,线程是操作系统调度的基本单位,一个进程...

    iOS多线程 (pthread,NSThread)简单Demo

    在iOS中,除了pthread和NSThread,还有其他多线程实现方式,如GCD(Grand Central Dispatch)和NSOperationQueue,它们通常比pthread和NSThread更高效、更易用。GCD是Apple的底层多线程框架,提供了并发编程的高级...

    IOS应用源码之多线程编程.zip

    本资源“IOS应用源码之多线程编程.zip”显然是一个专门探讨iOS多线程编程的代码集合,包含了示例源码和可能的相关教程。 一、多线程简介 在iOS开发中,多线程主要用于实现应用的并发执行,让程序的不同部分可以在...

    iOS开发学习之iOS多线程和RunLoop.pdf

    在iOS开发中,多线程编程是一个非常重要的概念,它允许应用程序同时执行多个操作,而不会相互干扰,从而提高程序的性能和响应能力。另外,RunLoop是iOS中一个非常重要的概念,它是事件接收循环,用于处理异步事件,...

    IOS多线程编程的3种实现方法

    iOS中有以下3种多线程编程方法: NSThread Grand Centeral Dispatch(GCD) NSOperation和NSOperationQueue 1.NSThread 这是最轻量级的多线程的方法,使用起来最直观的多线程编程方法。但是因为需要自己管理线程的...

    iOS多线程编程指南(二)线程管理 - 51CTO.COM1

    在iOS开发中,多线程编程是不可或缺的一部分,它能够帮助开发者实现应用的高效执行,尤其是在处理耗时操作时,如网络请求、大数据计算等。本文将深入探讨iOS中的线程管理,帮助开发者理解如何优雅地处理多线程任务。...

    ios 多线程编程指南.pdf

    ### iOS多线程编程知识点详解 #### 一、多线程编程概述 多线程编程是一种软件技术,它允许在单个应用程序内并行执行多个代码路径。这有助于提高应用程序的响应性和整体性能,尤其是在利用现代多核处理器的能力时。...

Global site tag (gtag.js) - Google Analytics