多线程

多线程的使用是为了避免UI界面的卡死。在子线程中进行耗时间的操作,完成后回到主线程进行UI的显示和刷新。
注意:(1)、在子线程中不要操作UI(不能操作UI)。(2)、子线程里面不要再创建子线程。(3)、主线程只负责UI的刷新和用户的交互。
线程的创建有如下几种方法:
1、同步创建线程

[self sync];
//同步是指所有的任务按次序执行(在一个线程中执行)
//会阻塞UI
-(void)sync
{
    [self task1];
    [self task2];
    [self task3];
}
-(void)task1
{
    sleep(1);
    NSLog(@"%s,%@",__func__,[NSDate date]);
}

-(void)task2
{
    sleep(2);
    NSLog(@"%s,%@",__func__,[NSDate date]);
}

-(void)task3
{
    sleep(3);
    NSLog(@"%s,%@",__func__,[NSDate date]);
}

2、异步 异步创建线程有4+1个c语言的方法
(1)、使用系统的方法

[self systemThread];
//直接调用UI中封装的方法,使用最简单 (在iOS8中好像不支持这些方法了)
-(void)systemThread
{
    [self performSelectorInBackground:@selector(task1) withObject:nil];
    [self performSelectorInBackground:@selector(task2) withObject:nil];
    [self performSelectorInBackground:@selector(task3) withObject:nil];
    //
    [self performSelectorInBackground:@selector(downLoadAction) withObject:nil];
}
-(void)task1
{
    sleep(1);
    NSLog(@"%s,%@",__func__,[NSDate date]);
}

-(void)task2
{
    sleep(2);
    NSLog(@"%s,%@",__func__,[NSDate date]);
}

-(void)task3
{
    sleep(3);
    NSLog(@"%s,%@",__func__,[NSDate date]);
}
-(void)downLoadAction
{
    NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:@"http://image16-c.poco.cn/mypoco/myphoto/20140605/18/17457026820140605181136033_640.jpg?570x300_120"]];
    UIImage *img = [UIImage imageWithData:data];
    [self performSelectorOnMainThread:@selector(downloadFinished:) withObject:img waitUntilDone:YES];
    NSLog(@"download");
}

(2)、NSThread方法

[self nsthread];
//NSThread是OC封装的一套开辟子线程的类
-(void)nsthread
{
    [NSThread detachNewThreadSelector:@selector(task1) toTarget:self withObject:nil];
    [NSThread detachNewThreadSelector:@selector(task2) toTarget:self withObject:nil];
    //或者用下面的方法,但需要手动开启
    NSThread *th = [[NSThread alloc]initWithTarget:self selector:@selector(task3) object:nil];
    [th start];
}
-(void)task1
{
    sleep(1);
    NSLog(@"%s,%@",__func__,[NSDate date]);
}

-(void)task2
{
    sleep(2);
    NSLog(@"%s,%@",__func__,[NSDate date]);
}
-(void)task3
{
    sleep(3);
    NSLog(@"%s,%@",__func__,[NSDate date]);
}

(3)、NSOperation

[self nsoperation];
-(void)nsoperation
{
    //创建多个任务
    NSInvocationOperation *opt1 = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(task1) object:nil];
    NSInvocationOperation *opt2 = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(task2) object:nil];
    NSInvocationOperation *opt3 = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(task3) object:nil];
    //创建一个线程队列,将任务加入到线程队列中
    NSOperationQueue *queue = [[NSOperationQueue alloc]init];
    [queue addOperation:opt1];
    [queue addOperation:opt2];
    [queue addOperation:opt3];
    //或者用下面的方面创建线程队列
    [queue addOperationWithBlock:^{
        sleep(4);
        NSLog(@"block:%@",[NSDate date]);
    }];
}

-(void)blockOperation{

    //NSBlockOperation默认会在当前线程执行。但是 NSBlockOperation 还有一个方法:addExecutionBlock: ,通过这个方法可以给 Operation 添加多个执行 Block。这样operation中的任务会并发执行,它会在主线程和其它多个线程中执行这些任务

    //1.创建NSBlockOperation对象
    NSBlockOperation *operation=[NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"%@",[NSThread currentThread]);
    }];
    // 添加多个Block
    for (NSInteger i=0; i<5; i++) {
        [operation addExecutionBlock:^{
            NSLog(@"第%ld次:%@",i,[NSThread currentThread]);
        }];
    }
    //开始任务
    [operation start];

    //NOTE:addExecutionBlock 方法必须在 start() 方法之前执行,否则就会报错:
}

-(void)operationQueue{
//    //因为主队列比较特殊,所以会单独有一个类方法来获得主队列。那么通过初始化产生的队列就是其他队列了,因为只有这两种队列,除了主队列,其他队列就不需要名字了。
//    //注意:其他队列的任务会在其他线程并行执行
//    
//    //1.创建一个其他队列
//    NSOperationQueue *queue=[[NSOperationQueue alloc] init];
//    //2.创建NSBlockOperation对象
//    NSBlockOperation *operation=[NSBlockOperation blockOperationWithBlock:^{
//        NSLog(@"%@",[NSThread currentThread]);
//    }];
//    //3.添加多个Block
//    for (NSInteger i=0; i<5; i++) {
//        [operation addExecutionBlock:^{
//             NSLog(@"第%ld次:%@",i,[NSThread currentThread]);
//        }];
//    }
    //设置最大并发数 当设置为1时 就变成串行
    queue.maxConcurrentOperationCount=1;
//    //4.队列添加到任务
//    [queue addOperation:operation];



    //NSBlockOperation还有一个非常实用的功能,那就是添加依赖。比如有 3 个任务:A: 从服务器上下载一张图片,B:给这张图片加个水印,C:把图片返回给服务器。这时就可以用到依赖了:
    //1.任务一:下载图片
    NSBlockOperation *operation1=[NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"下载图片 - %@",[NSThread currentThread]);
        [NSThread sleepForTimeInterval:1.0];
    }];
    //2.任务二:打水印
    NSBlockOperation *operation2=[NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"打水印 - %@",[NSThread currentThread]);
        [NSThread sleepForTimeInterval:1.0];
    }];
    //3.任务三:上传图片
    NSBlockOperation *operation3=[NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"上传图片 - %@",[NSThread currentThread]);
        [NSThread sleepForTimeInterval:1.0];
    }];
    //4.设置依赖
    //任务二依赖任务一
    [operation2 addDependency:operation1];
    //任务三依赖任务二
    [operation3 addDependency:operation2];
    //5.创建队列并加入任务
    NSOperationQueue *queue=[[NSOperationQueue alloc] init];

    //参数二:NSOperationQueue是并行的,所以加入该队列的任务都会在其他线程并行执行,不会阻塞主线程。但如果参数二为YES的话主线程会阻塞,直到queue中的任务执行完成
    [queue addOperations:@[operation1,operation2,operation3] waitUntilFinished:NO];

    NSLog(@"完成");
}

(4)、gcd 本身是c语言,特点是高效、简洁

[self gcd];

//GCD:大中枢分发,grand centeral dispatch
//它是基于C语言的,基于Blocks 
-(void)gcd
{
   [self baseQueue];
   [self standard];
   [self group];
   [self barrier];
   [self timeAfter];
   [self apply];
}

//如果线程队列是同步的,或者加入线程队列的方式是同步加入,执行所有的任务肯定是同步地
    //*********
    //要想所有的任务都异步执行,必须线程队列是异步队列,同时,加入的任务方式也是异步地

    //创建线程队列
    //第二个参数表示创建的队列是同步队列还是异步队列
    //DISPATCH_QUEUE_SERIAL:同步队列
    //DISPATCH_QUEUE_CONCURRENT:异步队列
-(void)baseQueue
{
//#if NO
    dispatch_queue_t qt = dispatch_queue_create("com.1000phone", DISPATCH_QUEUE_CONCURRENT);

    //async是异步地将一个任务(Blocks)加到队列中
    dispatch_async(qt, ^{
        [self task1];
    });
    dispatch_async(qt, ^{
        [self task2];
    });
    dispatch_async(qt, ^{
        [self task3];
    });
//#endif

#if NO
    //线程队列是异步地
    dispatch_queue_t qt = dispatch_queue_create("com.1000phone", DISPATCH_QUEUE_CONCURRENT);

    //sync是同步地将一个任务(Blocks)加到队列中
    dispatch_sync(qt, ^{
        [self task1];
    });
    dispatch_sync(qt, ^{
        [self task2];
    });
    dispatch_sync(qt, ^{
        [self task3];
    });
#endif
}

//标准用法
    //系统自带的线程队列
    //系统自带的有5个线程队列
-(void)standard
{
    dispatch_async(dispatch_get_global_queue(0, 0), ^{

        //子线程的部分
        NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:@"http://image16-c.poco.cn/mypoco/myphoto/20140605/18/17457026820140605181136033_640.jpg?570x300_120"]];
        UIImage *img = [UIImage imageWithData:data];

        //回到主线程
        dispatch_async(dispatch_get_main_queue(), ^{
            UIImageView *imgv = [[UIImageView alloc]initWithFrame:CGRectMake(10, 100, 300, 200)];
            imgv.image = img;
            [self.view addSubview:imgv];
        });

    });
}

//线程组
-(void)group
{
    //线程组的作用,用来监视一组任务的执行完成状态 
    dispatch_group_t gt = dispatch_group_create();
    //创建一个线程队列
    dispatch_queue_t qt = dispatch_queue_create("com", DISPATCH_QUEUE_SERIAL);
    dispatch_group_async(gt, qt, ^{
        [self task1];
    });
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        [self task2];
    });
    dispatch_group_async(gt, qt, ^{
        [self task3];
    });

    //所有在线程组中的任务执行完成以后,调用以下方法
    dispatch_group_notify(gt, dispatch_get_global_queue(2, 0), ^{
        NSLog(@"gt中的所有任务已经执行完成");
    });
}

//分组执行
-(void)barrier
{
    dispatch_queue_t qt = dispatch_queue_create("com", DISPATCH_QUEUE_CONCURRENT);
    dispatch_async(qt, ^{
        [self task1];
    });
    dispatch_async(qt, ^{
        [self task2];
    });

    //中断:有一个前提,线程队列必须是自己创建的:不能用系统自带的线程队列
    dispatch_barrier_async(qt, ^{
        NSLog(@"++++++++++++++");
    });

    dispatch_async(qt, ^{
        [self task3];
    });
    dispatch_async(qt, ^{
        NSLog(@"---%@",[NSDate date]);
    });
}

//延时执行任务   (其和NSTimer的效果一样,不过都说这种方法用起来显得逼格更高一些,哎哎)
-(void)timeAfter
{
    //高端
    dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, NSEC_PER_SEC * 5ull);
    //第一个参数是执行该任务的时间点
    //第二个参数是在哪个线程队列中执行
    //第三个参数是任务
    dispatch_after(time, dispatch_get_main_queue(), ^{
        self.view.backgroundColor = [UIColor purpleColor];
    });
}

-(void)apply
{
    NSMutableArray *_dataArray = [[NSMutableArray alloc]init];
    for (int i = 0; i<20000; i++) {
        [_dataArray addObject:[NSString stringWithFormat:@"model %d",i]];
    }
    //处理互相之间不影响的相似操作,和下标的次序没有关系
    NSLog(@"--%@",[NSDate date]);
    //2015-01-14 14:34:07.251 
    dispatch_apply(_dataArray.count, dispatch_get_global_queue(0, 0), ^(size_t n) {
        NSLog(@"%@",_dataArray[n]);
    });
    NSLog(@"==%@",[NSDate date]);
    //2015-01-14 14:34:14.688
    NSLog(@"--%@",[NSDate date]);
    for (NSString *str in _dataArray) {
        NSLog(@"%@",str);
    }
    NSLog(@"==%@",[NSDate date]);
    //2015-01-14 14:34:23.671
}

哈哈,码完了,那么多总是记不住,用到的时候再回来看看。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
SQLAlchemy 是一个 SQL 工具包和对象关系映射(ORM)库,用于 Python 编程语言。它提供了一个高级的 SQL 工具和对象关系映射工具,允许开发者以 Python 类和对象的形式操作数据库,而无需编写大量的 SQL 语句。SQLAlchemy 建立在 DBAPI 之上,支持多种数据库后端,如 SQLite, MySQL, PostgreSQL 等。 SQLAlchemy 的核心功能: 对象关系映射(ORM): SQLAlchemy 允许开发者使用 Python 类来表示数据库表,使用类的实例表示表中的行。 开发者可以定义类之间的关系(如一对多、多对多),SQLAlchemy 会自动处理这些关系在数据库中的映射。 通过 ORM,开发者可以像操作 Python 对象一样操作数据库,这大大简化了数据库操作的复杂性。 表达式语言: SQLAlchemy 提供了一个丰富的 SQL 表达式语言,允许开发者以 Python 表达式的方式编写复杂的 SQL 查询。 表达式语言提供了对 SQL 语句的灵活控制,同时保持了代码的可读性和可维护性。 数据库引擎和连接池: SQLAlchemy 支持多种数据库后端,并且为每种后端提供了对应的数据库引擎。 它还提供了连接池管理功能,以优化数据库连接的创建、使用和释放。 会话管理: SQLAlchemy 使用会话(Session)来管理对象的持久化状态。 会话提供了一个工作单元(unit of work)和身份映射(identity map)的概念,使得对象的状态管理和查询更加高效。 事件系统: SQLAlchemy 提供了一个事件系统,允许开发者在 ORM 的各个生命周期阶段插入自定义的钩函数。 这使得开发者可以在对象加载、修改、删除等操作时执行额外的逻辑。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值