zoukankan      html  css  js  c++  java
  • (IOS)多线程开发

    一、线程的使用

    以向网络请求一张图片为例

    -(void)downURL:(NSURL *)aURL
    {
        NSData *d = [NSData dataWithContentsOfURL:aURL];
        UIImage *img = [UIImage imageWithData:d];
        //imgView.image = img;
        // 切换回主线程执行UI的操作
        [imgView performSelectorOnMainThread:@selector(setImage:) withObject:img waitUntilDone:NO];
    }

    方法1:系统后台执行

    [self performSelectorInBackground:@selector(downURL:) withObject:url];

    方法2:利用C级的NSThread执行

    [NSThread detachNewThreadSelector:@selector(downURL:) toTarget:self withObject:url];    // 分派线程执行一个方法,静态方法创建了线程,并开始执行
    
    NSThread *t1 = [[NSThread alloc] initWithTarget:self selector:@selector(downURL:) object:url];
    [t1 start];     // 创建具体线程对象需要触发开始

    方法3:利用OC级的NSOperation执行,此处使用的是NSOperation的子类NSInvocationOperation(或NSBlockOperation)去执行,因为NSOperation只是一个抽象类,不能直接实例化使用

    NSInvocationOperation *op1 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(downURL:) object:url];
    [op1 setQueuePriority:NSOperationQueuePriorityNormal]
    NSInvocationOperation *op2 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(downURL:) object:url];
    //[op1 start];   // 线程对象不放到队列中的话需要触发开始
    
    queue = [[NSOperationQueue alloc] init];
    queue.maxConcurrentOperationCount = 1;  // 设置队列同时执行线程最大数
    [queue addOperation:op1];   // 队列会自动打开线程
    [queue addOperation:op2];
    [op1 release];
    [op2 release];

    方法4:继承NSOperation自定义线程类,利用target-action机制

    -(void)someMethod
    {
        BIDImageOperation *op = [[BIDImageOperation alloc] initWithTarget:self Selector:@selector(refreshUI:) URL:url1];
        [op start];
        // [op release];
    }
    
    -(void)refreshUI:(UIImage *)aImg
    {
        [imgView performSelectorOnMainThread:@selector(setImage:) withObject:aImg waitUntilDone:NO];
    }
    using
    #import <Foundation/Foundation.h>
    
    @interface BIDImageOperation : NSOperation
    {
        NSString *_imgURL;
        id _target;
        SEL _action;
    }
    
    @property (nonatomic,retain) NSString *imgURL;
    @property (nonatomic,assign) id target;
    @property (nonatomic,assign) SEL action;
    
    -(id)initWithTarget:(id)aTarget Selector:(SEL)aSelector URL:(NSString *)aURL;
    
    @end
    
    ######################################
    
    #import "BIDImageOperation.h"
    
    @implementation BIDImageOperation
    @synthesize imgURL = _imgURL,target = _target,action = _action;
    
    -(id)initWithTarget:(id)aTarget Selector:(SEL)aSelector URL:(NSString *)aURL
    {
        if (self = [super init]) {
            self.imgURL = aURL;
            self.target = aTarget;
            self.action = aSelector;
        }
        return self;
    }
    
    -(void)main
    {
        if ([self isCancelled]) {
            return;
        }
        
        NSURL *url = [NSURL URLWithString:self.imgURL];
        NSData *data = [NSData dataWithContentsOfURL:url];
        UIImage *img = [UIImage imageWithData:data];
        
        if ([self isCancelled]) {
            return;
        }
        
        [self.target performSelector:self.action withObject:img];
    }
    
    @end
    custom thread

    二、线程安全

    以一个售票服务的程序为例

    1.锁

    -(void)someMethod
    {
        NSThread *t1 = [[NSThread alloc] initWithTarget:self selector:@selector(saleTicket) object:nil];
        t1.name = @"window1";
        [t1 start];
    
        NSThread *t2 = [[NSThread alloc] initWithTarget:self selector:@selector(saleTicket) object:nil];
        t2.name = @"window2";
        [t2 start];
        //[NSThread detachNewThreadSelector:@selector(saleTicket) toTarget:self withObject:nil];
    }
    
    -(void)saleTicket
    {
        while (1) 
        {
            [lock lock];   // 对可能出现互斥的变量设置部分进行锁定
            if (count>0) 
            {
                count = 100 - ticket;
                NSLog(@"%@ 卖出:%d 剩余:%d",[NSThread currentThread].name,ticket,count);
                ticket++;
            } else {
                [lock unlock];
                break;
            }
            [lock unlock];
        }
    }

    2.取消

    [op cancel];并不能将线程取消掉,因为该方法是建议关闭而已,除非线程里的main或调用的方法中有对这个建议做接受处理,如下

    if ([self isCancelled]) // or  if([op isCancelled])
    {
         return;
    }

    在dealloc方法中,自定义线程类的成员变量都应该添加[op cancel];,队列则需要添加[queue cancelAllOperations];来停止退出线程。

  • 相关阅读:
    因为这几个TypeScript代码的坏习惯,同事被罚了500块
    如何设计好分布式数据库,这个策略很重要
    线程、多线程和线程池,看完这些你就能全部搞懂了
    章方:征服耶鲁教授的算法大神程序媛
    从零开始学python | 使用Python映射,过滤和缩减函数:所有您需要知道的
    c# 优化代码的一些规则——用委托表示回调[五]
    mysql 重新整理——索引优化explain字段介绍一 [九]
    mysql 重新整理——索引优化explain简单介绍 [八]
    mysql 重新整理——索引简介[七]
    mysql 重新整理——七种连接join连接[六]
  • 原文地址:https://www.cnblogs.com/mingfung-liu/p/3408243.html
Copyright © 2011-2022 走看看