dispatch_apply的用法

并行模拟for循环,将指定的代码循环10次,一般会把这些代码附加到一个queue上,然后在 dispatch_apply里并行

dispatch_queue_t queue = dispatch_get_globel_queue(DISPATCH_QUEUE_PREORITY_DEFAULT,0)

dispatch_apply(10, queue, ^(size_t index){

  NSLog("并行执行--%@",index);

});

dispatch_apply_f的用法

dispatch_apply 和 dispatch_apply_f 是同步函数,会阻塞当前线程直到所有循环迭代执行完成。当提交到并发queue时,循环迭代的执行顺序是不确定的

dispatch_after

延迟指定时间之后执行任务

dispatch_after(dispatch_time_t when, dispatch_queue_t queue, ^(void)block)

when:延迟执行时间 一般是一个这样的时间函数: dispatch_time(DISPATCH_TIME_NOW, (int64_t)(10 * NSEC_PER_SEC))

queue:队列 dispatch_get_main_queue()或者 dispatch_get_global_queue()

block:执行的任务

dispatch_once

dispatch_once(dispatch_once_t *predicate, ^(void)block)

predicate: 用来判断需要执行的任务是否执行完成

block :需要执行的一次性任务

+ (instantClass *)sharedClient {

  static instantClass *_sharedClient = nil;

  static dispatch_once_t onceToken;

  dispatch_once(&onceToken, ^{

     _sharedClient = [[instantClass alloc] init];

  });

   return _sharedClient;

}

dispatch_group

dispatch_grpup,把若干个任务放到一个dispatch group中

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PREORITY_DEFAULT,0);

dispatch_queue_group group = dispatch_group_craete();

dispatch_group_aysnc(group, queue,^{

  //do some async work

});

dispatch_group_async 和 dispatch_async一样,会把任务放到queue中执行,只不过它比dispatch_async多了一步操作,就是把这个任务和group相关联,

把这些任务放到group之后,我们可以调用dispatch_group_wait来等待任务完成。若任务已经全部完成或者为空,直接返回,否则等待所有任务完成之后返回。注意返回之后任务清空。

dispatch_group_wait(group,DISPATCH_TIME_FORVER);

dispatch_release(group);

dispatch_semaphore信号量

GCD信号量机制

信号量就是一些有限可数的资源。比如打印机,假如系统有两台打印机。但同时又5个任务要使用打印机,那么只有2个任务能同时进行打印,剩下3个要等待着2个任务打印完。那么程序工作过程应该是:任务首先获取打印机资源(dispatch_semaphore_wait),如果没有打印机可用了就要等待,直到其他任务用完这个打印机。当任务获取到打印机,就开始执行打印任务。任务用完打印机工作后,就必须把占用打印机释放(dispatch_semaphore_signal),以便其他任务可以接着打印。

//创建资源的信号量,只创建一次,比如2台打印机,那么 RESOURCE_SIZE为2.

dispatch_semaphore_t sema = dispatch_semaphore_create(RESORCE_SIZE);

//如果任务使用一个资源时,使用前调用dispatch_semaphore_wait,用完后dispatch_semaphore_signal.

//下面的代码可能在多个线程中调用多次

dispathc_semaphore_wait(sema, DISPATCH_TIME_FORVER);

//do some work here , the work will use one resource.

dispatch_semaphore_signal(sema);

信号量必须在资源使用之前调用dispatch_semaphore_create创建,而且只创建一次,RESOURCE_SIZE是可用资源总数。使用资源时dispatch_semaphore_wait将资源的可用数减少一个,如果当前没有可用资源了,将会等待直到其他线程回收资源,即调用dispatch_semaphore_signal让可用资源增加。用完资源后调用dispatch_semaphore_signal回收可利用资源。资源可用数将增加一个。

如果是生产者-消费者模型的花,RESOURCE_SIZE可能最初为0,那么生产者调用dispatch_semaphore_signal来生产一个单位的资源,消费者调用dispatch_semaphore_wait来消费(减少)一个单位的资源。当资源不足时,消费者会一直等待到资源数大于0,即生产者生成新的资源。

dispatch source(定时器,进程,文件,Mach port相关)

dispatch source 是GCD中监听一些系统事件的,有个Dispatch对象,它包括定时器、文件监听、进程监听,Mach port 监听等类型。

可以通过dispatch_source_create创建一个Dispatch Source:

dispatch_source_t dispatch_source_cerate(

  dispatch_source_type_t type,

  uintptr_t handle,

  unsigned long mask,

  dispatch_queue_t queue);

这里可以指定Dispatch Source 的类型, type可以为文件读或写、进程监听等。handel为监听对象的句柄,如果是文件就是文件描述符,如果是进程就是进程ID, mask用来指定一些想要监听的时间,它的意义取决于type.queue指定事件处理的任务队列。

创建好dispatch source 之后,我们要为 dispatch source 设置一个事件处理模块。可以用dispatch_source_set_event_handler或者dispatch_source_set_event_hander_f来设置:

void dispatch_source_source_set_event_handler(

  dispatch_source_t source,

  dispatch_block_t handler

)

设置好Dispatch Source 后就可以调用dispatch_resume来启动监听。

如果相应的事件发生就会触发事件处理模块。

同时我么也可以设置一个取消处理模块:

dispatch_source_set_cancel_handler(mySource, ^{

  //Close a file descriptor opened earlier.

  close(fd);

});

取消处理模块会在Dispatch Source 取消时调用。

定时器

定时器 Dispatch Source 可以每隔一个固定的时间处理一下任务。

dispatch_source_t CreateDispatchTimer(uint64_t interval, uint64 leeway, dispatch_queue_t queue, dispatch_block_t block){

  dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0 , queue);

  if(timer){

    dispatch_source_set_timer(timer, dispatch_walltime(NULL, 0), interval, leeway);

    dispatch_source_set_event_handler(timer, block);

    dispatch_resume(timer);

  }

  return timer;

}

void MyCreateTimer(){

  dispatch_source_t aTimer = CreateDispatchTimer(30ull * NSEC_PER_SEC,1ull * NSEC_PER_SEC, dispatch_get_main_queue(), ^{ MyPeriodicTask();})

//Store it somewhere for later use

  if(aTimer){

    MyStoreTimer(aTimer);

  }

}

监听文件事件

监听文件事件分好几个类型,有读、写、属性的监听

读取文件

dispatch_source_t source = dispatch_source_create(DISPATCH_SOURCE_TYPE_READ, fd ,0, queue);

dispatch_source_set_event_handler(source, ^{

  //get some data form the source variable, which is captured

  //form the parent context.

  size_t estimated = dispatch_source_get_data(source);

  //continue reading the descriptor

});

dispatch_resume(source);

写文件

dispatch_source_t writeSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_WRITE, fd, 0 , queue);

if(!writeSource){

  close(fd);

  return NULL;

}

dispatch_source_set_event_handeler(writeSource, ^{

  size_t bufferSize = MyGetDataSize();

  void *buffer = malloc(bufferSize);

  size_t actual = MyGetData(buffer, bufferSize);

  write(fd, buffer, actual);

  

  free(buffer);

  

  //cancel and release the dispatch source when done.

  dispatch_source_cancel(writeSource);

});

监听文件属性

dispatch_source_t source = dispatch_source_create(DISPATCH_SOURCE_TYPE_VNODE, fd, DISPATCH_VNODE_RENAME, QUEUE);

if(source){

  //copy the filename for ater use

  int length = strlen(filename);

  char * newString = (char*) malloc(length + 1);

  new String = strcpy(newString , filename);

  dispatch_set_context(source, newString);

  

  //install the event handler to process the name change dispatch_source_set_event_handeler(source, ^{

    const char* oldFilename = (char*)dispatch_get_context(source);

    MyUpdateFileName(oldFilename, fd);

  });

  //Install a cancellation handler to free the descriptor

  //and the stored string

  dispatch_source_set_cancel_hander(source, ^{

    char *fileStr = (char*)dispatch_get_context(source);

    free(fileStr);

    close(fd);

  });

  

  // Start processing events.

  dispatch_resume(source);

}else{

  close(fd);

}

监听进程事件

DISPATCH_PROC_EXIT是一个监听进程退出的类型。

dispatch_source_t source = dispatch_source_create(DISPATCH_SOURCE_TYPE_PROC, parentPID, DISPATCH_PROC_EXIT, queue);

if(source){

  dispatch_source_set_event_handler(source, ^{

    MySetAppExitFlag();

    dispatch_source_cancel(source);

    dispatch_rellease(source);

  });

  dispach_resume(source);

}

监听中断信号

dispatch_source_t source = dispatch_create_source(DISPATCH_SOURCE_TYPE_SIGNAL, SIGHUP, 0, queue);

if(source){

  dispatch_source_set_event_handler(source, ^{

    MyProcessSIGHUP();

  });

//Start processing signals

dispatch_requme(source);

}

												

GCD之各种派发的更多相关文章

  1. GCD 大中枢派发 简单应用实例

    @interface ViewController () { UIImageView* iv; UIButton* btn; UILabel* lbl; } @end @implementation ...

  2. iOS 多线程 之 GCD(大中枢派发)(一)

    导语: 本文个人原创,转载请注明出处(http://www.cnblogs.com/pretty-guy/p/8126981.html) 在iOS开发中多线程操作通常是一下3种,本文着重介绍Dispa ...

  3. iOS 多线程 之 GCD(大中枢派发)(二)

    本文接着上一篇讲.主要讲:dispatch_source. dispatch_source主要用户监听事件,可以监听如下事件 DISPATCH_SOURCE_TYPE_DATA_ADD DISPATC ...

  4. 修改版: 小伙,多线程(GCD)看我就够了,骗你没好处!

    多线程(英语:multithreading),是指从软件或者硬件上实现多个线程并发执行的技术.具有多线程能力的计算机因有硬件支持而能够在同一时间执行多于一个线程,进而提升整体处理性能.具有这种能力的系 ...

  5. effective OC2.0 52阅读笔记(六 块与大中枢派发)

    派发队列:dispatch_queue 操作队列:NSOperationQueue  组:dispathc_group_t 37 理解“块”这一概念 总结:块就是一个值,且自有其相关类型.块的强大之处 ...

  6. IOS 多线程05-OperationQueue 、GCD详解

      注:本人是翻译过来,并且加上本人的一点见解. 1. 开始 目前在 iOS中有两套先进的同步 API 可供我们使用:操作队列OperationQueue和 GCD .其中 GCD 是基于 C 的底层 ...

  7. App开发流程之使用GCD

    GCD即为Grand Central Dispatch的缩写,是一种主要用于异步处理任务的安全的高性能解决方案. 在此不对比其他异步处理技术,只记录GCD的使用及说明. 先记录一些必要的概念:线程,同 ...

  8. 多线程技术 NSThread & NSOperation & GCD

    多线程:在iOS开发中,用到多线程的处理问题的时候有很多,比如异步下载数据时刷新界面等等. 引入多线程来处理问题的关键就是,基于多线程可以使界面更加流畅,防止界面假死. 界面假死:比如你单击一个按钮来 ...

  9. iOS的三种多线程技术NSThread/NSOperation/GCD

    1.iOS的三种多线程技术 1.NSThread 每个NSThread对象对应一个线程,量级较轻(真正的多线程) 2.以下两点是苹果专门开发的"并发"技术,使得程序员可以不再去关心 ...

随机推荐

  1. iOS 解决UIScrollView布局问题(布局受statusBar和NavigationBar影响)

    iOS APP中有一个非常好用的功能,那就是当我们在滚动一个UIScrollView滚动了很远很远的时候,假如我们想让UIScrollView回到顶部,我们绝大多数人的做法就是慢慢慢慢的滚动UIScr ...

  2. 【代码审计】CLTPHP_v5.5.3 前台任意文件上传漏洞分析

      0x00 环境准备 CLTPHP官网:http://www.cltphp.com 网站源码版本:CLTPHP内容管理系统5.5.3版本 程序源码下载:https://gitee.com/chich ...

  3. Selenium 管理 Cookies

    使用 Selenium ,还可以方便地对 Cookies 进行操作,例如获取.添加 .删除 Cookies 等 from selenium import webdriver browser = web ...

  4. Android--Led_Demo_APK控制LED灯

    下面代码主要实现接口定义,实现从.so库文件接口函数在JAVA里面的声明:package com.friendlyarm.AndroidSDK; import android.util.Log; pu ...

  5. 两台Linux主机互传文件可以使用SCP命令来实现

    当两台linux主机之间要互传文件时可使用SCP命令来实现 复制文件: (1)将本地文件拷贝到远程 scp 文件名 --用户名@计算机IP或者计算机名称:远程路径 (2)从远程将文件拷回本地 scp ...

  6. bool和BOOL类型知识集合

    知识点一.C语言中有bool类型吗? 转自http://blog.csdn.net/liuqiqi677/article/details/6703615 之前一直都没有注意到,最近在用C语言写DSP算 ...

  7. IOS设计模式第七篇之观察者设计模式

    版权声明:原创作品,谢绝转载!否则将追究法律责任. 观察者设计模式 在观察者设计模式里面,一个对象通知其他的对象一些状态的改变.涉及这些对象不需要知道另一个对象---因此鼓励解耦设计模式.这个设计模式 ...

  8. ActiveMQ 消息持久化到数据库(Mysql、SQL Server、Oracle、DB2等)

    ActiveMQ具体就不介绍了,直接介绍如何讲ActiveMQ持久化到本地数据库,以SQL Server 2008 R2为例1.下载ActiveMQ后直接解压,我下载的是apache-activemq ...

  9. spring整合websocket通信

    1. maven依赖 <?xml version="1.0" encoding="UTF-8"?> <project xmlns=" ...

  10. 开发常见错误之 : IMP-00058: 遇到 ORACLE 错误 1691

    IMP-00058: 遇到 Oracle 错误 1691ORA-01691: Lob 段YQPRO.SYS_LOB0000031467C00006$$无法通过128(在表空间YQPRO中)扩展这种情况 ...