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];来停止退出线程。

  • 相关阅读:
    java.lang.AbstractMethodError: Method com/mchange/v2/c3p0/impl/NewProxyPreparedStatement.isClosed()Z is abstract
    Spring MVC controller控制器映射无法访问问题!!!
    关于 use-default-filters 属性的说明
    Spring MVC工程 无法拦截到url请求
    Caused by: java.lang.ClassNotFoundException: org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter
    Spring事务
    MySQL几个join
    解决CentOS7关闭/开启防火墙出现Unit iptables.service failed to load: No such file or directory.
    【Mybatis架构】Mapper映射文件中的#{}与${}
    空指针异常(从辅助类获取对象之后需要实例化才能保存信息)
  • 原文地址:https://www.cnblogs.com/mingfung-liu/p/3408243.html
Copyright © 2011-2022 走看看