iOS开发之类别、扩展(共3篇)
1.iOS开发之类别、扩展 篇一
前言:一块资源可能会被多个线程共享,也就是多个线程可能会访问同一块资源,比如多个线程访问同一个对象、同一个变量、同一个文件和同一个方法等,因此当多个线程访问同一块资源时,很容易会发生数据错误及数据不安全等问题。因此要避免这些问题,我们需要使用“线程锁”来实现。
本文主要论述IOS创建锁的方法(总结):
一、使用关键字
1)@synchronized(互斥锁)
优点:使用@synchronized关键字可以很方便地创建锁对象,而且不用显式的创建锁对象。
缺点:会隐式添加一个异常处理来保护代码,该异常处理会在异常抛出的时候自动释放互斥锁。而这种隐式的异常处理会带来系统的额外开销,为优化资源,你可以使用锁对象。
二、“Object-C”语言
1)NSLock(互斥锁)
2)NSRecursiveLock(递归锁)
条件锁,递归或循环方法时使用此方法实现锁,可避免死锁等问题。
3)NSConditionLock(条件锁)
使用此方法可以指定,只有满足条件的时候才可以解锁。
4)NSDistributedLock(分布式锁)
在IOS中不需要用到,也没有这个方法,因此本文不作介绍,这里写出来只是想让大家知道有这个锁存在。
如果想要学习NSDistributedLock的话,你可以创建MAC OS的项目自己演练,方法请自行Google,谢谢。
三、C语言
1)pthread_mutex_t(互斥锁)
2)GCD-信号量(“互斥锁”)
3)pthread_cond_t(条件锁)
线程安全 —— 锁
一、使用关键字:
1)@synchronized
// 实例类person
Person *person = [[Person alloc] init];
// 线程A
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
@synchronized(person) {
[person personA];
[NSThread sleepForTimeInterval:3]; // 线程休眠3秒
}
});
// 线程B
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
@synchronized(person) {
[person personB];
}
});
关键字@synchronized的使用,锁定的对象为锁的唯一标识,只有标识相同时,才满足互斥。如果线程B锁对象person改为self或其它标识,那么线程B将不会被阻塞。你是否看到@synchronized(self) ,也是对的。它可以锁任何对象,描述为@synchronized(anObj)。
二、Object-C语言
1)使用NSLock实现锁
// 实例类person
Person *person = [[Person alloc] init];
// 创建锁
NSLock *myLock = [[NSLock alloc] init];
// 线程A
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[myLock lock];
[person personA];
[NSThread sleepForTimeInterval:5];
[myLock unlock];
});
// 线程B
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[myLock lock];
[person personB];
[myLock unlock];
});
程序运行结果:线程B会等待线程A解锁后,才会去执行线程B。如果线程B把lock和unlock方法去掉之后,则线程B不会被阻塞,这个和synchronized的一样,需要使用同样的锁对象才会互斥。
NSLock类还提供tryLock方法,意思是尝试锁定,当锁定失败时,不会阻塞进程,而是会返回NO。你也可以使用lockBeforeDate:方法,意思是在指定时间之前尝试锁定,如果在指定时间前都不能锁定,也是会返回NO。
注意:锁定(lock)和解锁(unLock)必须配对使用
2)使用NSRecursiveLock类实现锁
// 实例类person
Person *person = [[Person alloc] init];
// 创建锁对象
NSRecursiveLock *theLock = [[NSRecursiveLock alloc] init];
// 创建递归方法
static void (^testCode)(int);
testCode = ^(int value) {
[theLock tryLock];
if (value > 0)
{
[person personA];
[NSThread sleepForTimeInterval:1];
testCode(value - 1);
}
[theLock unlock];
};
//线程A
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
testCode(5);
});
//线程B
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[theLock lock];
[person personB];
[theLock unlock];
});
如果我们把NSRecursiveLock类换成NSLock类,那么程序就会死锁。因为在此例子中,递归方法会造成锁被多次锁定(Lock),所以自己也被阻塞了。而使用NSRecursiveLock类,则可以避免这个问题。
3)使用NSConditionLock(条件锁)类实现锁:
使用此方法可以创建一个指定开锁的条件,只有满足条件,才能开锁。
// 实例类person
Person *person = [[Person alloc] init];
// 创建条件锁
NSConditionLock *conditionLock = [[NSConditionLock alloc] init];
// 线程A
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[conditionLock lock];
[person personA];
[NSThread sleepForTimeInterval:5];
[conditionLock unlockWithCondition:10];
});
// 线程B
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[conditionLock lockWhenCondition:10];
[person personB];
[conditionLock unlock];
});
线程A使用的是lock方法,因此会直接进行锁定,并且指定了只有满足10的情况下,才能成功解锁,
unlockWithCondition:方法,创建条件锁,参数传入“整型”。lockWhenCondition:方法,则为解锁,也是传入一个“整型”的参数。
三、C语言
1)使用pthread_mutex_t实现锁
注意:必须在头文件导入:#import
// 实例类person
Person *person = [[Person alloc] init];
// 创建锁对象
__block pthread_mutex_t mutex;
pthread_mutex_init(&mutex, NULL);
// 线程A
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
pthread_mutex_lock(&mutex);
[person personA];
[NSThread sleepForTimeInterval:5];
pthread_mutex_unlock(&mutex);
});
// 线程B
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
pthread_mutex_lock(&mutex);
[person personB];
pthread_mutex_unlock(&mutex);
});
实现效果和上例的相一致
2)使用GCD实现“锁”(信号量)
GCD提供一种信号的机制,使用它我们可以创建“锁”(信号量和锁是有区别的,具体请自行百度)。
// 实例类person
Person *person = [[Person alloc] init];
// 创建并设置信量
dispatch_semaphore_t semaphore = dispatch_semaphore_create(1);
// 线程A
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
[person personA];
[NSThread sleepForTimeInterval:5];
dispatch_semaphore_signal(semaphore);
});
// 线程B
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
[person personB];
dispatch_semaphore_signal(semaphore);
});
效果也是和上例介绍的相一致。
我在这里解释一下代码。dispatch_semaphore_wait方法是把信号量加1,dispatch_semaphore_signal是把信号量减1。
我们把信号量当作是一个计数器,当计数器是一个非负整数时,所有通过它的线程都应该把这个整数减1。如果计数器大于0,那么则允许访问,并把计数器减1。如果为0,则访问被禁止,所有通过它的线程都处于等待的状态。
3)使用POSIX(条件锁)创建锁
// 实例类person
Person *person = [[Person alloc] init];
// 创建互斥锁
__block pthread_mutex_t mutex;
pthread_mutex_init(&mutex, NULL);
// 创建条件锁
__block pthread_cond_t cond;
pthread_cond_init(&cond, NULL);
// 线程A
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
pthread_mutex_lock(&mutex);
pthread_cond_wait(&cond, &mutex);
[person personA];
pthread_mutex_unlock(&mutex);
});
// 线程B
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
pthread_mutex_lock(&mutex);
[person personB];
[NSThread sleepForTimeInterval:5];
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mutex);
});
效果:程序会首先调用线程B,在5秒后再调用线程A。因为在线程A中创建了等待条件锁,线程B有激活锁,只有当线程B执行完后会激活线程A。
pthread_cond_wait方法为等待条件锁。
pthread_cond_signal方法为激动一个相同条件的条件锁。
简单总结:
一般来说,如果项目不大,我们都会偷点懒,直接使用关键字@synchronized建立锁,懒人方法。其次可以使用苹果提供的OC方法,最后才会去使用C去建立锁。
2.iOS开发之类别、扩展 篇二
当执行那些与 UI 无关的任务,或者与 UI 交互的任务时,和执行其他任务一样,会需要大量时间,以上情况会经常出现,我们可以使用 dispatch_sync函数在一个分派队列上执行同步任务。你必须做的事情就是提供一个此队列的句柄了,这个队列必须运行任务,并且一个代码块会在这个队列上执行。 今天我们就来学习一下GCD执行非UI的操作。
2 代码实例
TestDemo.h
[plain]
#import
@interface TestDemo : NSObject
-(void)testMethod;
-(void)testMethod2;
@end
#import
@interface TestDemo : NSObject
-(void)testMethod;
-(void)testMethod2;
@end
TestDemo.m
[plain]
#import “TestDemo.h”
@implementation TestDemo
/**************Objc Method Start*********/
//Block Object
void (^printFrom1To1000)(void) = ^{
NSUInteger counter = 0;
for (counter = 1;counter <= 1000;counter++){
NSLog(@“Counter = %lu - Thread = %@”,
(unsigned long)counter,
[NSThread currentThread]);
}
};
//测试方法
-(void)testMethod{
/*
Dispatch_get_global_queue 函数的第一个参数说明了并发队列的优先级,这个属性 GCD 必须替程序员检
索。优先级越高,将提供更多的 CPU Timeslice 来获取该队列执行的代码。
Dispatch_get_global_queue 函数的第一个参数:
DISPATCH_QUEUE_PRIORITY_LOW
您的任务比正常任务用到更少的 Timeslice。
DISPATCH_QUEUE_PRIORITY_DEFAULT
执行代码的默认系统优先级将应用于您的任务。
DISPATCH_QUEUE_PRIORITY_HIGH
和正常任务相比,更多的 Timeslices 会应用到你的任务中。
Dispatch_get_global_queue 函数的第二个参数已经保存了,只要一直给它输入数值 0 就可以了。
*/
dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_sync(concurrentQueue, printFrom1To1000);
dispatch_sync(concurrentQueue, printFrom1To1000);
}
/**************Objc Method End*********/
/**************C Method Start*********/
//Block Object
void print2From1To1000(void *paramContext){
NSUInteger counter = 0; for (counter = 1;counter <= 1000;counter++){
NSLog(@“Counter = %lu - Thread = %@”,
(unsigned long)counter, [NSThread currentThread]);
}
}
//测试方法
-(void)testMethod2{
/*
*/
dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_sync_f(concurrentQueue, NULL,print2From1To1000);
dispatch_sync_f(concurrentQueue, NULL,print2From1To1000);
}
/**************C Method End*********/
@end
#import “TestDemo.h”
@implementation TestDemo
/**************Objc Method Start*********/
//Block Object
void (^printFrom1To1000)(void) = ^{
NSUInteger counter = 0;
for (counter = 1;counter <= 1000;counter++){
NSLog(@“Counter = %lu - Thread = %@”,
(unsigned long)counter,
[NSThread currentThread]);
}
};
//测试方法
-(void)testMethod{
/*
Dispatch_get_global_queue 函数的第一个参数说明了并发队列的优先级,这个属性 GCD 必须替程序员检
索,
优先级越高,将提供更多的 CPU Timeslice 来获取该队列执行的代码。
Dispatch_get_global_queue 函数的第一个参数:
DISPATCH_QUEUE_PRIORITY_LOW
您的任务比正常任务用到更少的 Timeslice。
DISPATCH_QUEUE_PRIORITY_DEFAULT
执行代码的默认系统优先级将应用于您的任务。
DISPATCH_QUEUE_PRIORITY_HIGH
和正常任务相比,更多的 Timeslices 会应用到你的任务中。
Dispatch_get_global_queue 函数的第二个参数已经保存了,只要一直给它输入数值 0 就可以了。
*/
dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_sync(concurrentQueue, printFrom1To1000);
3.iOS开发之类别、扩展 篇三
WHC_RadioButton.h头文件如下:
//// WHC_RadioButton.h// CTBMobileBank//// Created by 吴海超 on 15/4/1.////#import#define KWHC_IMAGE_SIZE (15.0) //图标尺寸@interface WHC_RadioButton : UIButton@end
WHC_RadioButton.m源文件如下:
【iOS开发之类别、扩展】推荐阅读:
iOS开发、设计面试题10-06
IOS开发培训课程未来发展优势08-23
论文期刊类别09-29
教科研课题类别06-28
风险类别及管控措施11-04
建筑物类别等级划分06-18
教师资格证申报类别08-17
停电事故类别及处置程序08-20
考生类别到底是什么意思10-06
托福阅读常考话题类别梳理09-01