obj-c利用dispatch库并发示例
我们首先写一个纯C的程序,代码的功能为显示指定范围整数中素数的个数:
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <math.h>
#include <time.h>
#include <unistd.h>
typedef unsigned long long ULL;
bool is_prime(x){
ULL j = sqrtl(x + 1);
if(x==2) return true;
if(x<2 || x%2 == 0) return false;
for(ULL i = 3;i<=j;i = i+2){
if(x%i == 0) return false;
}
return true;
}
ULL p_count(ULL start,ULL end){
ULL count = 0;
for(ULL i = start;i<=end;i++){
if(is_prime(i)) count++;
}
return count;
}
bool is_neg_num_ll(long long x){
if(x < 0)
return true;
else
return false;
}
int main(int argc,char **argv){
ULL start_x,end_x;
if(argc <=1){
printf("usage : %s [start_num] end_num\n",argv[0]);
return 1;
}
if(argc == 2){
sscanf(argv[1],"%llu",&end_x);
if(is_neg_num_ll((long long)end_x)){
printf("end_num %llu must not neg num!\n",end_x);
return 2;
}
start_x = 0;
}
if(argc == 3){
sscanf(argv[1],"%llu",&start_x);
sscanf(argv[2],"%llu",&end_x);
if(is_neg_num_ll((long long)start_x) || is_neg_num_ll((long long)end_x)){
printf("start_num %llu or end_num %llu must not neg num!\n",\
start_x,end_x);
return 3;
}
if(start_x >= end_x){
printf("start_num %llu must < end_num %llu\n",start_x,end_x);
return 4;
}
}
printf("notice:calc from %llu to %llu\n",start_x,end_x);
int begin = clock();
ULL count = p_count(start_x,end_x);
double stop = ((1.0 * (clock() - begin)) / CLOCKS_PER_SEC) * 1000.0;
printf("in range (%llu - %llu) p_count is %llu (take %f ms)\n",start_x,end_x,count,stop);
return 0;
}
代码很简单,如果只指定一个参数end,则返回0-end中素数个数,如果指定2个参数start和end则返回(start-end)中素数的个数(包含start和end在内)。
下面引入dispatch机制,我们看看并发操作怎么写:
#import <Foundation/Foundation.h>
//#include "/usr/local/include/dispatch/dispatch.h"
typedef unsigned long long ULL;
typedef struct {
ULL start;
ULL end;
}range_t,*prange_t;
bool is_prime(x){
ULL j = sqrtl(x + 1);
if(x==2) return true;
if(x<2 || x%2 == 0) return false;
for(ULL i = 3;i<=j;i = i+2){
if(x%i == 0) return false;
}
return true;
}
ULL p_count(ULL start,ULL end){
ULL count = 0;
for(ULL i = start;i<=end;i++){
if(is_prime(i)) count++;
}
return count;
}
range_t get_range(int index){
switch(index){
case 0:
return (range_t){1,10000};
case 1:
return (range_t){10001,20000};
case 2:
return (range_t){20001,30000};
case 3:
return (range_t){30001,40000};
}
return (range_t){-1,-1};
}
static ULL g_count = 0;
static NSNumber *g_lock_count = nil;
void callback(void *context){
prange_t pr = context;
NSLog(@"range : (%llu - %llu)",pr->start,pr->end);
ULL count = p_count(pr->start,pr->end);
@synchronized(g_lock_count){
g_count += count;
}
}
void function_way(void){
g_lock_count = @1;
range_t range_ary[4] = {{1,100000},{100001,200000},{200001,300000},{300001,400000}};
//FIXME:dispatch_queue_create make crash!!!
dispatch_queue_t queue = dispatch_queue_create("WorkBlocks",NULL);
//dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0);
dispatch_group_t group = dispatch_group_create();
///*
for(int i = 0;i<4;i++){
dispatch_group_async_f(group,queue,&range_ary[i],callback);
}
dispatch_group_wait(group,DISPATCH_TIME_FOREVER);
//*/
//dispatch_release(queue);
NSLog(@"at last! count is %llu",g_count);
}
void apply_way(void){
dispatch_queue_t queue = dispatch_queue_create("WorkBlocks",NULL);
ULL __block last_count = 0;
NSNumber *lock_count = @2;
dispatch_apply(4,queue,^(size_t i){
range_t r = get_range(i);
NSLog(@"IDX:%lu:range is (%llu - %llu)",i,r.start,r.end);
ULL count = p_count(r.start,r.end);
@synchronized(lock_count){
last_count += count;
}
});
NSLog(@"at last! count is %llu",last_count);
}
void group_way(void){
NSNumber *lock_index = @1;
NSNumber *lock_count = @2;
ULL __block last_count = 0;
int __block work_index = 0;
//range_t range_ary[4] = {{1,100},{101,200},{201,300},{301,400}};
//FIXME:dispatch_queue_create make crash!!!
dispatch_queue_t queue = dispatch_queue_create("WorkBlocks",NULL);
//dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0);
dispatch_group_t group = dispatch_group_create();
///*
dispatch_block_t task = ^(void){
int index = work_index;
NSLog(@"my work index is %d",index);
@synchronized(lock_index){
++work_index;
}
range_t r = get_range(index);
ULL count = p_count(r.start,r.end);
@synchronized(lock_count){
last_count += count;
}
};
for(int i = 0;i<4;i++){
dispatch_group_async(group,queue,task);
}
dispatch_group_wait(group,DISPATCH_TIME_FOREVER);
//*/
//dispatch_release(queue);
NSLog(@"at last! count is %llu",last_count);
}
int main(void){
@autoreleasepool{
//group_way();
//apply_way();
function_way();
}
return 0;
}
代码中采用3中形式的并发:
- group_way
- apply_way
- function_way
细节可以查看代码。
obj-c利用dispatch库并发示例的更多相关文章
- Python:利用 selenium 库抓取动态网页示例
前言 在抓取常规的静态网页时,我们直接请求对应的 url 就可以获取到完整的 HTML 页面,但是对于动态页面,网页显示的内容往往是通过 ajax 动态去生成的,所以如果是用 urllib.reque ...
- C/C++ 开源库及示例代码
C/C++ 开源库及示例代码 Table of Contents 说明 1 综合性的库 2 数据结构 & 算法 2.1 容器 2.1.1 标准容器 2.1.2 Lockfree 的容器 2.1 ...
- CocoaPods的安装及使用/利用开源库Diplomat实现分享及第三方登录/git的使用
<<史上最简洁版本>> 1.gem sources -l查看 当前的源 //1.1 sudo -i..以下都是以管理员的身份来操作的 2.gem sources --remov ...
- python3:利用smtplib库和smtp.qq.com邮件服务器发送邮件
python3:利用smtplib库和smtp.qq.com邮件服务器发送邮件 使用qq的邮件服务器需要注意的两个地方主要是: 1.协议问题 使用465端口 SSL 协议 2.口令问题 出现SMTPA ...
- 记一次C++编程引用obj文件作为静态库文件
简介 常用静态库文件的名字一般是 ***.lib ,例如 nisyscfg.lib 就是一个静态库文件,但是一个例程居然是引用 **.obj 文件作为静态库,有点非常规啊. 这是一个NI488.2 的 ...
- c# 利用动态库DllImport("kernel32")读写ini文件(提供Dmo下载)
c# 利用动态库DllImport("kernel32")读写ini文件 自从读了设计模式,真的会改变一个程序员的习惯.我觉得嘛,经验也可以从一个人的习惯看得出来,看他的代码编写习 ...
- php学习笔记:利用gd库生成图片,并实现随机验证码
说明:一些基本的代码我都进行了注释,这里实现的验证码位数.需要用的字符串都可以再设置.有我的注释,大家应该很容易能看得懂. 基本思路: 1.用mt_rand()随机生成数字确定需要获取的字符串,对字符 ...
- libJPEG-turbo库使用示例代码
libJPEG库是用于编码数据为JPEG格式或者解码JPEG格式图片的常用库,OpenCV读取图像底层实现就是利用libJPEG库,而libJPEG-turbo则效率更高. 具体怎么编译编译libJP ...
- RAC集群数据库连库代码示例(jdbc thin方式,非oci)
1.RAC集群数据库连库代码示例(jdbc thin方式,非oci):jdbc.driverClassName=oracle.jdbc.driver.OracleDriverjdbc.url=jdbc ...
随机推荐
- Zookeeper总概
zookeeper是一个开源的分布式协调服务.是典型的分布式数据一致性的解决方案. zookeeper可以保证以下分布式一致性的特性 1. 顺序性:同一客户端发起的事务请求,最终会严格的按照发出顺序应 ...
- Retrofit 2.0 超能实践(三),轻松实现文件/多图片上传/Json字符串
文:http://blog.csdn.net/sk719887916/article/details/51755427 Tamic 简书&csdn同步 通过前两篇姿势的入门 Retrofit ...
- 【ShaderToy】基础篇之再谈抗锯齿(antialiasing,AA)
写在前面 在之前的基础篇中,我们讲到了在绘制点线时如何处理边缘的锯齿,也就是使用smoothstep函数.而模糊参数是一些定值,或者是跟屏幕分辨率相关的数值,例如分辨率宽度的5%等等.但这种方法其实是 ...
- 1052. Linked List Sorting (25)
题目如下: A linked list consists of a series of structures, which are not necessarily adjacent in memory ...
- UNIX环境高级编程——进程间通信概念
进程间通信 --- IPC1. 进程间通信的目的a. 数据传输: 一个进程需要将他的数据发送给另一个进程b. 资源共享: 多个进程之间共享同样的资源c. 通知事件: 一个进程需要向另一个或一组进程发送 ...
- java设计模式---调停者模式
中介者模式(Mediator):用一个中介对象来封装一系列的对象交互.中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互. 通用类图: 举例:在一个公司里面 ...
- JAVA之旅(二十二)——Map概述,子类对象特点,共性方法,keySet,entrySet,Map小练习
JAVA之旅(二十二)--Map概述,子类对象特点,共性方法,keySet,entrySet,Map小练习 继续坚持下去吧,各位骚年们! 事实上,我们的数据结构,只剩下这个Map的知识点了,平时开发中 ...
- 我眼中的Linux设备树(四 中断)
四 中断中断一般包括中断产生设备和中断处理设备.中断控制器负责处理中断,每一个中断都有对应的中断号及触发条件.中断产生设备可能有多个中断源,有时多个中断源对应中断控制器中的一个中断,这种情况中断产生设 ...
- Using mysqldump for Backups(备份还原数据库实例及参数详细说明)
官网mysqldump命令如下: Using mysqldump for Backups https://dev.mysql.com/doc/refman/5.7/en/using-mysqldump ...
- C++编译器何时为用户提供默认构造函数
第一种是类成员中有成员是类对象,并且该成员的类含有默认构造函数,那么C++编译器会帮你给这个类也生成一个默认构造函数,用来调用其成员对象的构造函数,完成该成员的初始化构造.需要强调的是,如果这个成员的 ...