iOS 多线程的四种技术方案 ![]()
image
pthread 实现多线程操作 代码实现:
void * run(void *param)
{
for (NSInteger i = 0; i < 1000; i++) {
NSLog(@"---buttonclick---%zd---%@", i, [NSThread currentThread]);
}
return NULL;
}
@implementation ViewController
- (IBAction)clickButton:(id)sender {
// 定义一个线程
pthread_t thread;
// 创建一个线程 (参1)pthread_t *restrict:创建线程的指针,(参2)const pthread_attr_t *restrict:线程属性 (参3)void *(*)(void *):线程执行的函数的指针,(参4)void *restrict:null
pthread_create(&thread, NULL, run, NULL);
// 何时回收线程不需要你考虑
pthread_t thread2;
pthread_create(&thread2, NULL, run, NULL);
}
NSThread实现多线程一个 NSThread 对象就代表一条线程 创建线程的多种方式
#pragma mark - 执行run方法
- (void)run:(NSString *)param
{
// 当前线程是否是主线程
for (NSInteger i = 0; i < 100; i++) {
NSLog(@"---%@---%zd---%d", [NSThread currentThread], i, [NSThread isMainThread]);
}
}
方法2和方法3的优点:快捷
-(UIImageView *)imageView
{
if (!_imageView) {
_imageView = [UIImageView new];
_imageView.frame = CGRectMake(0, 0, 300, 300);
_imageView.center = self.view.center;
[self.view addSubview:_imageView];
}
return _imageView;
}
- (void)viewDidLoad {
[super viewDidLoad];
//监听线程结束的通知
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handle_threadexit:) name:NSThreadWillExitNotification object:nil];
// Do any additional setup after loading the view.
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
//第一种方式:先创建再启动线程
// 创建线程
NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(run:) object:@"booob"];
// 线程启动了,事情做完了才会死, 一个NSThread对象就代表一条线程
[thread start];
//第二种:直接创建并启动线程
// 直接创建并启动线程
[NSThread detachNewThreadSelector:@selector(run:) toTarget:self withObject:@"wang"];
//第三种:
// 直接创建并启动线程
[self performSelectorInBackground:@selector(run:) withObject:@"wang000"];
// 使线程进入阻塞状态
[NSThread sleepForTimeInterval:2.0];
//例子
// 获取图片的url
NSURL *url = [NSURL URLWithString:@"https://pages.github.com/images/slideshow/yeoman.png"];
// 另开1条线程 object用于数据的传递
NSThread *thread3 = [[NSThread alloc] initWithTarget:self selector:@selector(downLoadWithURL:) object:url];
thread3.name = @"downloadimage...";
// 由于下面下载图片的耗时太长,应开启线程来完成
[thread3 start];
}
#pragma mark - 执行run方法
- (void)run:(NSString *)param
{
// 当前线程是否是主线程
for (NSInteger i = 0; i < 10; i++) {
NSLog(@"---%@---%zd---%d", [NSThread currentThread], i, [NSThread isMainThread]);
}
}
//线程直接的交互
// 下载图片
- (void)downLoadWithURL:(NSURL *)url
{
NSLog(@"%s ,%s %@",__FILE__,__FUNCTION__, [NSThread currentThread]);
// 下载图片
NSData *data = [NSData dataWithContentsOfURL:url];
// 生成图片
UIImage *image = [UIImage imageWithData:data];
// 返回主线程显示图片
[self.imageView performSelectorOnMainThread:@selector(setImage:) withObject:image waitUntilDone:YES];
}
//处理线程结束事件
-(void)handle_threadexit:(NSNotification *)notify
{
NSThread * thread = (NSThread *)notify.object;
NSLog(@"+++++++++++++++ 线程 %@ 结束 ++++++++++++",thread.name);
}
TIPS: 拓展,线程结束的通知 —————————————————————————————————————————— GCD 是如何实现多线程的
![]()
images
GCD会自动将队列中的任务取出,放到对应的线程,任务的取出遵循FIFO,即先入先出队列,First Input First Output 的缩写。
创建并发/串行队列代码:
- (void)viewDidLoad {
[super viewDidLoad];
dispatch_queue_t queue = dispatch_get_main_queue();
// 创建串行队列 serial 串行 concurrent并发
queueSerial = dispatch_queue_create("searial.whenbar.com", DISPATCH_QUEUE_SERIAL);
//创建并行队列
// 参1:const char *label 队列名称
// 参2:dispatch_queue_attr_t attr 队列类型
queueConcurrent = dispatch_queue_create("concurrent.whenbar.com", DISPATCH_QUEUE_CONCURRENT);
}
//1 获得主队列
-(void)runqueueMain
{
// 获取主队列 在主队列中的任务都会在主线程中执行。
dispatch_queue_t queueMain = dispatch_get_main_queue();
}
//2. 创建串行队列
-(void)runqueueSerial
{
// GCD同步函数串行队列(立即执行,当前线程)
// 参1: dispatch_queue_t queue 队列
// 参2: 任务
dispatch_sync(queueSerial, ^{
for (NSInteger i = 0; i < 10; i++) {
NSLog(@"~~~%ld %@",i, [NSThread currentThread]);
}
});
// 异步函数串行队列 (另开线程,多个任务按顺序执行)
dispatch_async(queueSerial, ^{
dispatch_async(queueSerial, ^{
for (NSInteger i = 0; i < 10; i++) {
NSLog(@"~~~%ld %@",i, [NSThread currentThread]);
}
});
dispatch_async(queueSerial, ^{
for (NSInteger i = 0; i < 10; i++) {
NSLog(@"~~~%ld %@",i, [NSThread currentThread]);
}
});
dispatch_async(queueSerial, ^{
for (NSInteger i = 0; i < 10; i++) {
NSLog(@"~~~%ld %@",i, [NSThread currentThread]);
}
});
});
}
//3. 创建并发队列
-(void)runqueueConcurrent
{
// 同步函数并行队列(立即执行,当前线程)
dispatch_sync(queueConcurrent, ^{
for (NSInteger i = 0; i < 10; i++) {
NSLog(@"~~~%ld %@",i, [NSThread currentThread]);
}
});
// 异步函数并行队列 (另开线程,多个任务一起执行)
dispatch_async(queueConcurrent, ^{
dispatch_async(queueConcurrent, ^{
for (NSInteger i = 0; i < 5; i++) {
NSLog(@"~~~%ld %@",i, [NSThread currentThread]);
}
});
dispatch_async(queueConcurrent, ^{
for (NSInteger i = 0; i < 6; i++) {
NSLog(@"~~~%ld %@",i, [NSThread currentThread]);
}
});
dispatch_async(queueConcurrent, ^{
for (NSInteger i = 0; i < 7; i++) {
NSLog(@"~~~%ld %@",i, [NSThread currentThread]);
}
});
});
}
//4. 创建全局队列
-(void)runqueueGlobal
{
// 获取全局队列 全局队列是并发队列
// 参1:队列的优先级
// 参2:0(以后可能用到的参数)//#define DISPATCH_QUEUE_PRIORITY_HIGH 2 // 高\
#define DISPATCH_QUEUE_PRIORITY_DEFAULT 0 // 默认(中)\
#define DISPATCH_QUEUE_PRIORITY_LOW (-2) // 低\
#define DISPATCH_QUEUE_PRIORITY_BACKGROUND INT16_MIN // 后台
dispatch_queue_t queueGlobal = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
}
// 主队列:(任何一个任务只要在主队列中,都会加入到主线程的队列中执行)
TIPS: 注意 GCD实现线程通信小项目:下载图片 代码如下:
// 获取图片的url
NSURL *url = [NSURL URLWithString:@"http://7xjanq.com1.z0.glb.clouddn.com/6478.jpg"];
// 开启线程下载图片
dispatch_queue_t queue = dispatch_queue_create("111", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(queue, ^{
NSData *data = [NSData dataWithContentsOfURL:url];
UIImage *image = [UIImage imageWithData:data];
// 下载完成后返回主线程显示图片
dispatch_async(dispatch_get_main_queue(), ^{
self.imageView.image = image;
});
});
———————————————————————————————————————— GCD其他常用函数 ![]()
image
//----------------- 队列组 -----------------------------
//队列组可以将很多队列添加到一个组里,这样做的好处是,当这个组里所有的任务都执行完了,队列组会通过一个方法通知我们。下面是使用方法,这是一个很实用的功能。
-(void)rungroup
{
//1.创建队列组
dispatch_group_t group=dispatch_group_create();
//2.创建队列
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0);
//3.多次使用队列组的方法执行任务, 只有异步方法
//3.1.执行3次循环
dispatch_group_async(group,queue,^{
for (NSInteger i = 0; i< 3; i++){
NSLog(@"group-01 - %@", [NSThread currentThread]);
}
});
//3.2.主队列执行8次循环
dispatch_group_async(group, dispatch_get_main_queue(), ^{
for (NSInteger i=0;i<8;i++) {
NSLog(@"group-02 - %@", [NSThread currentThread]);
}
});
//3.3.执行5次循环
dispatch_group_async(group, queue, ^{
for(NSInteger i=0;i<5;i++) {
NSLog(@"group-03 - %@", [NSThread currentThread]);
}
});
//4.都完成后会自动通知
dispatch_group_notify(group,dispatch_get_main_queue(),^{
NSLog(@"完成 - %@", [NSThread currentThread]);
});
}
dispatch_barrier 栅栏
// 1.barrier : 在barrier前面的先执行,然后再执行barrier,然后再执行barrier后面的 barrier的queue不能是全局的并发队列
dispatch_queue_t queue = dispatch_queue_create("11", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(queue, ^{
for (int i = 0; i < 100; i++) {
NSLog(@"%@--1", [NSThread currentThread]);
}
});
dispatch_async(queue, ^{
for (int i = 0; i < 100; i++) {
NSLog(@"%@--2", [NSThread currentThread]);
}
});
dispatch_barrier_async(queue, ^{
for (int i = 0; i < 100; i++) {
NSLog(@"%@--3", [NSThread currentThread]);
}
});
dispatch_async(queue, ^{
for (int i = 0; i < 100; i++) {
NSLog(@"%@--4", [NSThread currentThread]);
}
});
// dispatch_after 延迟执行
// 延迟执行
// 方法1
[self performSelector:@selector(run:) withObject:@"参数" afterDelay:2.0];
// 方法2
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
for (NSInteger i = 0; i < 100; i++) {
NSLog(@"%@", [NSThread currentThread]);
}
});
// 方法3
[NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:@selector(run:) userInfo:nil repeats:NO];
dispatch_once 整个程序运行中执行一次
// 整个程序中只执行一次
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
// 一次性代码
});
思考题:以下函数输出的结果是什么? ![]()
image
以下的代码输出是什么呢 ![]()
image
作用:实现某个类的单例对象 单例模式:在整个应用程序中,共享一份资源(这份资源只需要创建初始化1次)
//--------------单例模式--------------------
#if __has_feature(objc_instancetype)
#undef AS_SINGLETON
#define AS_SINGLETON( ... ) \
- (instancetype)sharedInstance; \
+ (instancetype)sharedInstance;
#undef DEF_SINGLETON
#define DEF_SINGLETON \
- (instancetype)sharedInstance \
{ \
return [[self class] sharedInstance]; \
} \
+ (instancetype)sharedInstance \
{ \
static dispatch_once_t once; \
static id __singleton__; \
dispatch_once( &once, ^{ __singleton__ = [[self alloc] init]; } ); \
return __singleton__; \
}
#undef DEF_SINGLETON
#define DEF_SINGLETON( ... ) \
- (instancetype)sharedInstance \
{ \
return [[self class] sharedInstance]; \
} \
+ (instancetype)sharedInstance \
{ \
static dispatch_once_t once; \
static id __singleton__; \
dispatch_once( &once, ^{ __singleton__ = [[self alloc] init]; } ); \
return __singleton__; \
}
#else // #if __has_feature(objc_instancetype)
#undef AS_SINGLETON
#define AS_SINGLETON( __class ) \
- (__class *)sharedInstance; \
+ (__class *)sharedInstance;
#undef DEF_SINGLETON
#define DEF_SINGLETON( __class ) \
- (__class *)sharedInstance \
{ \
return [__class sharedInstance]; \
} \
+ (__class *)sharedInstance \
{ \
static dispatch_once_t once; \
static __class * __singleton__; \
dispatch_once( &once, ^{ __singleton__ = [[[self class] alloc] init]; } ); \
return __singleton__; \
}
#endif // #if __has_feature(objc_instancetype)
#import "gcdfunViewController.h"
#pragma mark - 单例模式(责任编辑:最模板) |






Magento主题模板外贸创意模
人气:457
Prestashop英文医疗护理网站
人气:209
黑色苹果简洁风格|ecshop外
人气:1458
ecshop汽车配件类外贸模板
人气:1826
ecshop仿京东2012免费模板整
人气:10144
Vanesa 英文大型百货商城
人气:323