GVKun编程网logo

Swift - 多线程实现方式(3) - Grand Central Dispatch(GCD)(swift 多线程安全)

3

在这里,我们将给大家分享关于Swift-多线程实现方式的知识,让您更了解3-GrandCentralDispatch的本质,同时也会涉及到如何更有效地2017CCPC杭州J.MasterofGCD【差

在这里,我们将给大家分享关于Swift - 多线程实现方式的知识,让您更了解3 - Grand Central Dispatch的本质,同时也会涉及到如何更有效地2017CCPC 杭州 J. Master of GCD【差分标记 / 线段树 / GCD】、A Guide to Blocks & Grand Central Dispatch (and the Cocoa API's making use of them)、c# – Xamarin iOS中的Grand Central Dispatch vs ThreadPool性能、CodeForces - 582A GCD Table (map大数操作&gcd)好题的内容。

本文目录一览:

Swift - 多线程实现方式(3) - Grand Central Dispatch(GCD)(swift 多线程安全)

Swift - 多线程实现方式(3) - Grand Central Dispatch(GCD)(swift 多线程安全)

1,Swift继续使用Object-C原有的一套线程,包括三种多线程编程技术:
(1)NSThread
(2)Cocoa NSOperation(NSOperation和NSOperationQueue)
(3)Grand Central Dispath(GCD)

2,本文着重介绍Grand Central Dispath(GCD)
GCD是Apple开发的一个多核编程的解决方法,基本概念就是dispatch queue(调度队列),queue是一个对象,它可以接受任务,并将任务以先到先执行的顺序来执行。dispatch queue可以是并发的或串行的。GCD的底层依然是用线程实现,不过我们可以不用关注实现的细节。其优点有如下几点:
(1)易用:GCD比thread更简单易用。基于block的特效使它能极为简单地在不同代码作用域之间传递上下文。
(2)效率:GCD实现功能轻量,优雅,使得它在很多地方比专门创建消耗资源的线程更加实用且快捷。
(3)性能:GCD自动根据系统负载来增减线程数量,从而减少了上下文切换并增加了计算效率。
(4)安全:无需加锁或其他同步机制。

3,GCD三种创建队列的方法
(1)自己创建一个队列
第一个参数代表队列的名称,可以任意起名
第二个参数代表队列属于串行还是并行执行任务
串行队列一次只执行一个任务。一般用于按顺序同步访问,但我们可以创建任意数量的串行队列,各个串行队列之间是并发的。
并行队列的执行顺序与其加入队列的顺序相同。可以并发执行多个任务,但是执行完成的顺序是随机的。
1
2
3
4
5
//创建串行队列
var serial:dispatch_queue_t = dispatch_queue_create( "serialQueue1" , DISPATCH_QUEUE_SERIAL )
//创建并行队列
concurrent:dispatch_queue_t = dispatch_queue_create( "concurrentQueue1" DISPATCH_QUEUE_CONCURRENT )

(2)获取系统存在的全局队列
Global Dispatch Queue有4个执行优先级:
DISPATCH_QUEUE_PRIORITY_HIGH 高
DISPATCH_QUEUE_PRIORITY_DEFAULT 正常
DISPATCH_QUEUE_PRIORITY_LOW 低
DISPATCH_QUEUE_PRIORITY_BACKGROUND 非常低的优先级(这个优先级只用于不太关心完成时间的真正的后台任务)
1
globalQueue:dispatch_queue_t = dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT (3)运行在主线程的Main Dispatch Queue
正如名称中的Main一样,这是在主线程里执行的队列。应为主线程只有一个,所有这自然是串行队列。一起跟UI有关的操作必须放在主线程中执行。
1
var mainQueue:dispatch_queue_t = dispatch_get_main_queue()

4,添加任务到队列的两种方法
(1)dispatch_async异步追加Block块(dispatch_async函数不做任何等待)
1
2
3
4
5
6
7
8
9
10
//添加异步代码块到dispatch_get_global_queue队列
dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT Void in
//处理耗时操作的代码块...
println ( "do work" )
//操作完成,调用主线程来刷新界面
dispatch_async(dispatch_get_main_queue(),153) !important; background: none !important;">in
"main refresh" )
})
})
(2)dispatch_sync同步追加Block块
同步追加Block块,与上面相反。在追加Block结束之前,dispatch_sync函数会一直等待,等待队列前面的所有任务完成后才能执行追加的任务。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//添加同步代码块到dispatch_get_global_queue队列
//不会造成死锁,当会一直等待代码块执行完毕
dispatch_sync(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT Void in
println ( "sync1" )
})
"end1" )
//添加同步代码块到dispatch_get_main_queue队列
//会引起死锁
//因为在主线程里面添加一个任务,因为是同步,所以要等添加的任务执行完毕后才能继续走下去。但是新添加的任务排在
//队列的末尾,要执行完成必须等前面的任务执行完成,由此又回到了第一步,程序卡死
dispatch_sync(dispatch_get_main_queue(),{ () -> Void in
"sync2" )
})
"end2" )

5,暂停或者继续队列
这两个函数是异步的,而且只在不同的blocks之间生效,对已经正在执行的任务没有影响。
dispatch_suspend后,追加到Dispatch Queue中尚未执行的任务在此之后停止执行。
而dispatch_resume则使得这些任务能够继续执行。
6
//创建并行队列
conQueue:dispatch_queue_t = dispatch_queue_create( "concurrentQueue1" DISPATCH_QUEUE_CONCURRENT )
//暂停一个队列
dispatch_suspend(conQueue)
//继续队列
dispatch_resume(conQueue)

6,dispatch_once 一次执行
保证dispatch_once中的代码块在应用程序里面只执行一次,无论是不是多线程。因此其可以用来实现单例模式,安全,简洁,方便。
//往dispatch_get_global_queue队列中添加代码块,只执行一次
predicate:dispatch_once_t = 0
dispatch_once(&predicate,{ () -> Void in
//只执行一次,可用于创建单例
"work" )
})

7,dispatch_after 延迟调用
dispatch_after并不是在指定时间后执行任务处理,而是在指定时间后把任务追加到Dispatch Queue里面。因此会有少许延迟。注意,我们不能(直接)取消我们已经提交到dispatch_after里的代码。
//延时2秒执行
let delta = 2.0 * Double ( NSEC_PER_SEC dtime = dispatch_time( DISPATCH_TIME_NOW Int64 (delta))
dispatch_after(dtime,dispatch_get_global_queue( in
"延时2秒执行" }

8,多个任务全部结束后做一个全部结束的处理
dispatch_group_async:用来监视一组block对象的完成,你可以同步或异步地监视
dispatch_group_notify:用来汇总结果,所有任务结束汇总,不阻塞当前线程
dispatch_group_wait:等待直到所有任务执行结束,中途不能取消,阻塞当前线程
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
//获取系统存在的全局队列
queue:dispatch_queue_t = dispatch_get_global_queue( //定义一个group
group:dispatch_group_t = dispatch_group_create()
//并发任务,顺序执行
dispatch_group_async(group,queue,{() -> in
"block1" )
})
in
"block2" )
})
in
"block3" )
})
//所有任务执行结束汇总,不阻塞当前线程
dispatch_group_notify(group,dispatch_get_main_queue(),153) !important; background: none !important;">in
"group done" )
})
//永久等待,直到所有任务执行结束,中途不能取消,阻塞当前线程
result = dispatch_group_wait(group,147) !important; background: none !important;">DISPATCH_TIME_FOREVER )
if result == 0{
"任务全部执行完成" )
} else {
"某个任务还在执行" )
}

8,dipatch_apply 指定次数的Block最加到指定队列中
dipatch_apply函数是dispatch_sync函数和Dispatch Group的关联API。按指定的次数将指定的Block追加到指定的Dispatch Queue中,并等待全部处理执行结束。
因为dispatch_apply函数也与dispatch_sync函数一样,会等待处理结束,因此推荐在dispatch_async函数中异步执行dispatch_apply函数。dispatch_apply函数可以实现高性能的循环迭代。
16
//定义一个一步代码块
dispatch_async(queue,153) !important; background: none !important;">in
//通过dispatch_apply,循环变量数组
dispatch_apply(6,{(index) -> in
(index)
})
//执行完毕,主线程更新
in
"done" )
})
})

9,信号,信号量
dispatch_semaphore_create:用于创建信号量,可以指定初始化信号量计数值,这里我们默认1.
dispatch_semaphore_waite:会判断信号量,如果为1,则往下执行。如果是0,则等待。
dispatch_semaphore_signal:代表运行结束,信号量加1,有等待的任务这个时候才会继续执行。
24
//当并行执行的任务更新数据时,会产生数据不一样的情况
for i in 1...20
{
"\(i)" }
//使用信号量保证正确性
//创建一个初始计数值为1的信号
semaphore:dispatch_semaphore_t = dispatch_semaphore_create(1)
1...20
{
//永久等待,直到Dispatch Semaphore的计数值 >= 1
dispatch_semaphore_wait(semaphore,monospace !important; min-height: auto !important; background: none !important;">)
)
//发信号,使原来的信号计数值+1
dispatch_semaphore_signal(semaphore)
})
}

原文出自: www.hangge.com 转载请保留原文链接: http://www.hangge.com/blog/cache/detail_745.html

总结

以上是小编为你收集整理的Swift - 多线程实现方式(3) - Grand Central Dispatch(GCD)全部内容。

如果觉得小编网站内容还不错,欢迎将小编网站推荐给好友。

Swift相关文章

效率成吨提升之代码生成器-蓝湖工具神器iOS,Android,Swift,Flutter
软件简介:蓝湖辅助工具,减少移动端开发中控件属性的复制和粘贴.待开发的功能:1.支持自动生成约束2.开发设置页面3.做一个浏览器插件,支持不需要下载整个工程,可即时操作当前蓝湖浏览页面4.支持Flutter语言模板生成5.支持更多平台,如Sketch等6.支持用户自定义语言模板
【Audio音频开发】音频基础知识及PCM技术详解
现实生活中,我们听到的声音都是时间连续的,我们称为这种信号叫模拟信号。模拟信号需要进行数字化以后才能在计算机中使用。目前我们在计算机上进行音频播放都需要依赖于音频文件。那么音频文件如何生成的呢?音频文件的生成过程是将声音信息采样、量化和编码产生的数字信号的过程,我们人耳所能听到的声音频率范围为(20Hz~20KHz),因此音频文件格式的最大带宽是20KHZ。根据奈奎斯特的理论,音频文件的采样率一般在40~50KHZ之间。奈奎斯特采样定律,又称香农采样定律。...............
见过仙女蹦迪吗?一起用python做个小仙女代码蹦迪视频
前言最近在B站上看到一个漂亮的仙女姐姐跳舞视频,循环看了亿遍又亿遍,久久不能离开!看着小仙紫姐姐的蹦迪视频,除了一键三连还能做什么?突发奇想,能不能把舞蹈视频转成代码舞呢?说干就干,今天就手把手教大家如何把跳舞视频转成代码舞,跟着仙女姐姐一起蹦起来~视频来源:【紫颜】见过仙女蹦迪吗 【千盏】一、核心功能设计总体来说,我们需要分为以下几步完成:从B站上把小姐姐的视频下载下来对视频进行截取GIF,把截取的GIF通过ASCII Animator进行ASCII字符转换把转换的字符gif根据每
【Android App】实战项目之仿抖音的短视频分享App(附源码和演示视频 超详细必看)
【Android App】实战项目之仿抖音的短视频分享App(附源码和演示视频 超详细必看)
自定义ava数据集及训练与测试 完整版 时空动作/行为 视频数据集制作 yolov5, deep sort, VIA MMAction, SlowFast
前言这一篇博客应该是我花时间最多的一次了,从2022年1月底至2022年4月底。我已经将这篇博客的内容写为论文,上传至arxiv:https://arxiv.org/pdf/2204.10160.pdf欢迎大家指出我论文中的问题,特别是语法与用词问题在github上,我也上传了完整的项目:https://github.com/Whiffe/Custom-ava-dataset_Custom-Spatio-Temporally-Action-Video-Dataset关于自定义ava数据集,也是后台
【视频+源码】登录鉴权的三种方式:token、jwt、session实战分享
因为我既对接过session、cookie,也对接过JWT,今年因为工作需要也对接了gtoken的2个版本,对这方面的理解还算深入。尤其是看到官方文档评论区又小伙伴表示看不懂,所以做了这期视频内容出来:视频在这里:本期内容对应B站的开源视频因为涉及的知识点比较多,视频内容比较长。如果你觉得看视频浪费时间,可以直接阅读源码:goframe v2版本集成gtokengoframe v1版本集成gtokengoframe v2版本集成jwtgoframe v2版本session登录官方调用示例文档jwt和sess
【Android App】实战项目之仿微信的私信和群聊App(附源码和演示视频 超详细必看)
【Android App】实战项目之仿微信的私信和群聊App(附源码和演示视频 超详细必看)
零基础用Android Studio实现简单的本地视频播放器
用Android Studio的VideoView组件实现简单的本地视频播放器。本文将讲解如何使用Android视频播放器VideoView组件来播放本地视频和网络视频,实现起来还是比较简单的。VideoView组件的作用与ImageView类似,只是ImageView用于显示图片,VideoView用于播放视频。...
  • • 效率成吨提升之代码生成器-蓝湖工具神器
  • • 【Audio音频开发】音频基础知识及PCM技
  • • 见过仙女蹦迪吗?一起用python做个小仙
  • • 【Android App】实战项目之仿抖音的短视
  • • 自定义ava数据集及训练与测试 完整版 时
  • • 【视频+源码】登录鉴权的三种方式:tok
  • • 【Android App】实战项目之仿微信的私信
  • • 零基础用Android Studio实现简单的本地
  • • 采用MATLAB对正弦信号,语音信号进行生
  • • Keras深度学习实战(40)——音频生成
Flutterandroidiosswift抖音cocos2d小米cocos2dx三国杀kotlin-coroppococosandroid-jexcodeandroid-liaugmented-美好mutateandroid-gr加到arkitreact-naticnnandroid-cocrashlytic耳机java-nativexoplayerstockandroid-ar壁纸react-natiandroid-daandroid-wowatchosandroid-ca笔记本电脑buildozer装备android-al
  • 友情链接:
  • 菜鸟教程
  • 前端之家
  • 编程小课
  • 小编
  • -
  • 我要投稿
  • -
  • 广告合作
  • -
  • 联系我们
  • -
  • 免责声明
  • -
  • 网站地图
版权所有 © 2018 小编 闽ICP备13020303号-8
微信公众号搜索 “ 程序精选 ” ,选择关注!
微信公众号搜"程序精选"关注
微信扫一扫可直接关注哦!

2017CCPC 杭州 J. Master of GCD【差分标记 / 线段树 / GCD】

2017CCPC 杭州 J. Master of GCD【差分标记 / 线段树 / GCD】

给你一个 n 个初始元素都为 1 的序列和 m 个询问 q。 询问格式为:l r x (x 为 2or3) 最后求 1~n 所有数的 GCD GCD:把每个数分别分解质因数,再把各数中的全部公有质因数提取出来连乘,所得的积就是这几个数的最大公约数。

#include<cstdio>
#include<string>
#include<cstdlib>
#include<cmath>
#include<iostream>
#include<cstring>
#include<set>
#include<queue>
#include<algorithm>
#include<vector>
#include<map>
#include<cctype>
#include<stack>
#include<sstream>
#include<list>
#include<assert.h>
#include<bitset>
#include<numeric>
#define debug() puts("++++")
#define gcd(a,b) __gcd(a,b)
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define fi first
#define se second
#define pb push_back
#define sqr(x) ((x)*(x))
#define ms(a,b) memset(a,b,sizeof(a))
#define sz size()
#define be begin()
#define pu push_up
#define pd push_down
#define cl clear()
#define lowbit(x) -x&x
#define all 1,n,1
#define mod 998244353

#define pi acos(-1.0)
#define rep(i,x,n) for(int i=(x); i<(n); i++)
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int,int> P;
const int INF = 1<<30;
const int maxn = 1e5+3;
const double eps = 1e-8;
const int dx[] = {-1,1,0,0,1,1,-1,-1};
const int dy[] = {0,0,1,-1,1,-1,1,-1};
int dir[2]={-1,1};
const int mon[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
const int monn[] = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
LL t,n,m;
LL Pow(LL a, LL b)
{
    LL res=1;
    while(b)
    {
        if(b&1)
            res=(res%mod * a%mod)%mod;
        a = a%mod*a%mod;
        b>>=1;
    }
    return res%mod;
}
LL a[maxn],b[maxn];
int main()
{
    scanf("%lld",&t);
    while(t--)
    {
        ms(a,0),ms(b,0);
        scanf("%lld%lld",&n,&m);
        while(m--)
        {
            LL l,r,x;
            scanf("%lld%lld%lld",&l,&r,&x);
            if(x==2)
            {
                a[l]++,a[r+1]--; //差分标记因子含有2的数、区间加维护2or3的操作数
            }
            else
            {
                b[l]++,b[r+1]--;
            }
        }
        LL m1=a[1],m2=b[1];
        for(int i=2;i<=n;i++)
        {
            a[i]+=a[i-1]; //前缀和维护序列本身,而序列记录2的操作数即个数,得到具体每个数的操作数
            b[i]+=b[i-1];
            m1=min(m1,a[i]); //2的最小操作数
            m2=min(m2,b[i]);
        }
        LL ans = (Pow(2,m1)%mod*Pow(3,m2)%mod)%mod;
        printf("%lld\n",ans);
    }
}
/*
2
5 3
1 3 2
3 5 2
1 5 3
6 3
1 2 2
5 6 2
1 6 2

6 2
【题意】

【类型】

【分析】

【时间复杂度&&优化】

【trick】

【数据】

*/

A Guide to Blocks & Grand Central Dispatch (and the Cocoa API's making use of them)

A Guide to Blocks & Grand Central Dispatch (and the Cocoa API's making use of them)

Intro As you may or may not kNow I recently did a talk at the Des Moines Cocoaheads in which I reviewed Blocks and Grand Central dispatch. I have tried to capture the content of that talk and a lot more here in this article. The talk encompassed

  • Blocks
  • Grand Central dispatch
  • GCD Design Patterns
  • Cocoa API''s using GCD and Blocks

All of the content of this article applies only to Mac OS X 10.6 SNow Leopard as blocks support and Grand Central dispatch are only available there. There are alternate methods to get blocks onto Mac OS X 10.5 and the iPhone OS via projects likePlausible Blocks which have blocks support,though do not have Grand Central dispatch (libdispatch.)

Grand Central dispatch is Open Source I should mention that Apple has in fact Open Sourced libdispatch (Grand Central Dispatch) on Mac OS Forge and the other components like Kernel Support for GCD (although if implemented on other OS''s this is not necessary) and the blocks runtime support are all freely available and if you want you can even checkout the libdispatch repository using Git with the command git clone git://git.macosforge.org/libdispatch.git

Blocks

Blocks are part of a new C Language Extension,and are available in C,Objective-C,C++ and Objective-C++. Right off the bat,I should say that while we will use blocks with Grand Central dispatch a lot later on,they are not required when using Grand Central dispatch. Blocks are very useful onto themselves even if you never use them with anything else. However we gain a lot of benefit when we use blocks with Grand Central dispatch,so pretty much all my examples here will use blocks.

What are blocks? Well let me show you a very basic example of one

^{ NSLog(@"Inside a block"); }

This is a very basic example of a block,but it is basically a block that accepts no arguments and contains a NSLog() statement. Think of blocks as either a method or snippet of code that accepts arguments and captures lexical scope. Other languages have already had something like this concept implemented for a while (since the 70''s at least if I remember correctly.) Here''s a couple examples of this concept in one of my favorite languages Python

>>>f = lambda x,y,z: x + y + z
...
>>> f(2,3,4)
9

Here we are defining a lambda in Python which is basically a function that we can execute later on. In Python after the lambda keyword you define the arguments that you are passing in to the left of the colon and the right is the actual expression that will get executed. So in the first line of code we''ve defined a lambda that accepts 3 arguments and when it''s invoked all it will do is accept the arguments and add them together,hence when we invoke f like f(2,4) we get 9 back. We can do more with Python lambda''s. Python has functions that actually do more with lambdas like in this example...

>>>reduce((lambda x,y: x+y),[1,2,4])
10
>>>reduce((lambda x,y: x*y),4])
24

This reduce function uses a lambda that accepts 2 arguments to iterate over an array. The lambda in this case accepts 2 arguments (as the reduce function requires) and in the first example just iterates over the array with it. Python begins by calling the lambda using the first 2 elements of the array then gets a resulting value and again calls the lambda with that resulting value and the next element in the array and keeps on calling the lambda until it has fully iterated over the data set. So in other words the function is executed like so (((1 + 2) + 3) + 4)

Blocks bring this concept to C and do a lot more. You might ask yourself "But haven''t we already had this in C? I mean there are C Function Pointers." Well yeah,but while blocks are similar in concept,they do a lot more than C Function Pointers,and even better if you already kNow how to use C function pointers,Blocks should be fairly easy to pick up.

Here is a C Function Pointer Declaration...

 void (*func)(void); 

...and here is a Block Declaration...

 void (^block)(void); 

Both define a function that returns nothing (void) and takes no arguments. The only difference is that we''ve changed the name and swapped out a "*" for a "^". So lets create a basic block

 int (^MyBlock)(int) = ^(int num) { return num * 3; }; 

The block is laid out like so. The first part signifies that it''s a block returning an int. The (^MyBlock)(int) is defining a block of the MyBlock type that accepts an int as an argument. Then the ^(int num) to the right of the assignment operator is the beginning of the block,it means this is a block that accepts an int as an argument (matching the declaration earlier.) Then the { return num * 3; }; is the actual body of the block that will be executed.

When we''ve defined the block as shown earlier we can then assign it to variables and pass it in as arguments like so...

int aNum = MyBlock(3);

printf(“Num %i”,aNum); //9 

Blocks Capturing Scope: When I said earlier that blocks capture lexical scope this is what I mean,blocks are not only useful to use as a replacement for c function pointers,but they also capture the state of any references you use within the block itself. Let me show you...

int spec = 4;
 
int (^MyBlock)(int) = ^(int aNum){
 return aNum * spec;
};

spec = 0;
printf("Block value is %d",MyBlock(4));

Here we''ve done a few things. First I declared an integer and assigned it a value of 4. Then we created the block and assigned it to an actual block implementation and finally called the block in a printf statement. And finally it prints out "Block value is 16"? Wait we changed the spec number to 0 just before we called it didn''t we? Well yes actually we did. But what blocks do actually is create a const copy of anything you reference in the block itself that is not passed in as an argument. So in other words we can change the variable spec to anything we want after assigning the block,but unless we are passing in the variable as an argument the block will always return 16 assuming we are calling it as MyBlock(4). I should also note that we can also use C''s typedef utility to make referencing this type of block easier. So in other words...

int spec = 4;
 
typedef int (^MyBlock)(int);
 
MyBlock InBlock = ^(int aNum){
 return aNum * spec;
};

spec = 0;
printf("InBlock value is %d",InBlock(4));

is exactly equivalent to the prevIoUs code example. The difference being is that the latter is more readable.

__block Blocks do have a new storage attribute that you can affix onto variables. Lets say that in the prevIoUs example we want the block to read in our spec variable by reference so that when we do change the variable spec that our call toInBlock(4) actually returns what we expect it to return which is 0. To do so all we need to change is adding __block to spec like so...

__block int spec = 4;
 
typedef int (^MyBlock)(int);
 
MyBlock InBlock = ^(int aNum){
 return aNum * spec;
};

spec = 0;
printf("InBlock value is %d",245)"> and Now the printf statement finally spits out "InBlock value is 0",because Now it''s reading in the variable spec by reference instead of using the const copy it would otherwise use.

Blocks as Objective-C objects and more! Naturally going through this you''d almost be thinking right Now that blocks are great,but they Could potentially have some problems with Objective-C,not so Blocks are Objective-C objects! They do have a isa pointer and do respond to basic commands like -copy and -release which means we can use them in Objective-C dot Syntax like so...

@property(copy) void(^myCallback)(id obj);
@property(readwrite,copy) MyBlock inBlock;

and in your Objective-C code you can call your blocks just like so self.inBlock();.

Finally I should note that while debugging your code there is a new GDB command specifically for calling blocks like so

$gdb invoke-block MyBlock 12 //like MyBlock(12)
$gdb invoke-block StringBlock “\” String \”” 

These give you the ability to call your blocks and pass in arguments to them during your debug sessions.

Grand Central dispatch

Now onto Grand Central dispatch (which I may just reference as GCD from here on out.) Unlike past additions to Mac OS X like say NSOperation/NSThread Subclasses,Grand Central dispatch is not just a new abstraction around what we''ve already been using,it''s an entire new underlying mechanism that makes multithreading easier and makes it easy to be as concurrent as your code can be without worrying about the variables like how much work your cpu cores are doing,how many cpu cores you have and how much threads you should spawn in response. You just use the Grand Central dispatch API''s and it handles the work of doing the appropriate amount of work. This is also not just in Cocoa,anything running on Mac OS X 10.6 SNow Leopard can take advantage of Grand Central dispatch ( libdispatch ) because it''s included in libSystem.dylib and all you need to do is include #import <dispatch/dispatch.h> in your app and you''ll be able to take advantage of Grand Central dispatch.

Grand Central dispatch also has some other nice benefits. I''ve mentioned this before in other talks,but in OS design there are 2 main memory spaces (kernel space and user land.) When code you call executes a syscall and digs down into the kernel you pay a time penalty for doing so. Grand Central dispatch will try and do it''s best with some of it''s API''s and by pass the kernel to return to your application without digging into the kernel which means this is very fast. However if GCD needs to it can go down into the kernel and execute the equivalent system call and return back to your application.

Lastly GCD does some things that threading solutions in Leopard and earlier did not do. For example NSOperationQueue in Leopard took in NSOperation objects and created a thread,ran the NSOperation -(void)main on the thread and then killed the thread and repeated the process for each NSOperation object it ran,pretty much all we did on Leopard and earlier was creating threads,running them and then killing the threads. Grand Central dispatch however has a pool of threads. When you call into GCD it will give you a thread that you run your code on and then when it''s done it will give the thread back to GCD. Additionally queues in GCD will (when they have multiple blocks to run) just keep the same thread(s) running and run multiple blocks on the thread,which gives you a nice speed boost,and only then when it has no more work to do hand the thread back to GCD. So with GCD on SNow Leopard we are getting a nice speed boost just by using it because we are reusing resources over and over again and then we we aren''t using them we just give them back to the system.

This makes GCD very nice to work with,it''s very fast,efficient and light on your system. Even though GCD is fast and light however you should make sure that when you give blocks to GCD that there is enough work to do such that it''s worth it to use a thread and concurrency. You can also create as many queues as you want to match however many tasks you are doing,the only constraint is the memory available on the users system.

GCD API So if we have a basic block again like this

^{ NSLog(@"Doing something"); }

then to get this running on another thread all we need to do is use dispatch_async() like so...

dispatch_async(queue,^{
 NSLog(@"Doing something");
});

so where did that queue reference come from? Well we just need to create or get a reference to a Grand Central dispatch Queue ( dispatch_queue_t ) like this

dispatch_queue_t queue = dispatch_get_global_queue(0,0);

which just in case you''ve seen this code is equivalent to

dispatch_queue_t queue = dispatch_get_global_queue(disPATCH_QUEUE_PRIORITY_DEFAULT,245)"> In Grand Central dispatch the two most basic things you''ll deal with are queues (dispatch_queue_t) and the API''s to submit blocks to a queue such as dispatch_async() or dispatch_sync() and I''ll explain the difference between the two later on. For Now let''s look at the GCD Queues.

The Main Queue The Main Queue in GCD is analogous to the main app thread (aka the AppKit thread.) The Main Queue cooperates with NSApplicationMain() to schedule blocks you submit to it to run on the main thread. This will be very handy to use later on,for Now this is how you get a handle to the main queue

dispatch_queue_t main = dispatch_get_main_queue();

or you Could just call get main queue inside of a dispatch call like so

dispatch_async(dispatch_get_main_queue(),^ {....

The Global Queues The next type of queue in GCD are the global queues. You have 3 of them of which you can submit blocks to. The only difference to them are the priority in which blocks are dequeued. GCD defines the following priorities which help you get a reference to each of the queues...

enum {
 disPATCH_QUEUE_PRIORITY_HIGH = 2,disPATCH_QUEUE_PRIORITY_DEFAULT = 0,disPATCH_QUEUE_PRIORITY_LOW = -2,};

When you call dispatch_get_global_queue() with disPATCH_QUEUE_PRIORITY_HIGH as the first argument you''ve got a reference to the high global queue and so on for the default and low. As I said earlier the only difference is the order in which GCD will empty the queues. By default it will go and dequeue the high priority queue''s blocks,then dequeue the default queues blocks and then the low. This priority doesn''t really have anything to do with cpu time.

Private Queues Finally there are the private queues,these are your own queues that dequeue blocks serially. You can create them like so

dispatch_queue_t queue = dispatch_queue_create("com.MyApp.AppTask",NULL);

The first argument to dispatch_queue_create() is essentially a C string which represents the label for the queue. This label is important for several reasons

  • You can see it when running Debug tools on your app such as Instruments
  • If your app crashes in a private queue the label will show up on the crash report
  • As there are going to be lots of queues on 10.6 it''s a good idea to differentiate them

By default when you create your private queues they actually all point to the default global queue. Yes you can point these queues to other queues to make a queue hierarchy using dispatch_set_target_queue(). The only thing Apple discourages is making an loop graph where you make a queue that points to another and another eventually winding back to pointing at the first one because that behavior is undefined. So you can create a queue and set it to the high priority queue or even any other queue like so

dispatch_queue_t queue = dispatch_queue_create("com.App.AppTask,0);
dispatch_queue_t high = dispatch_get_global_queue(disPATCH_QUEUE_PRIORITY_HIGH,NULL);

dispatch_set_target_queue(queue,high);

If you wanted to you Could do the exact same with your own queues to create the queue hierarchies that I described earlier on.

Suspending Queues Additionally you may need to suspend queue''s which you can do with dispatch_suspend(queue). This runs exactly like NSOperationQueue in that it won''t suspend execution of the current block,but it will stop the queue dequeueing any more blocks. You should be aware of how you do this though,for example in the next example it''s not clear at all what''s actually run

irst Block"); }); dispatch_async(queue,^{ NSLog(@"Second Block"); }); dispatch_async(queue,^{ NSLog(@"Third Block"); }); dispatch_suspend(queue);

In the above example it''s not clear at all what has run,because it''s entirely possible that any combination of blocks may have run.

Memory Management It may seem a bit odd,but even in fully Garbage Collected code you still have to call dispatch_retain() and dispatch_release() on your grand central dispatch objects,because as of right Now they don''t participate in garbage collection.

Recursive Decomposition Now calling dispatch_async() is okay to run code in a background thread,but we need to update that work back in the main thread,how how would one go about this? Well we can use that main queue and justdispatch_async() back to the main thread from within the first dispatch_async() call and update the UI there. Apple has referred to this as recursive decomposition,and it works like this

dispatch_queue_t queue = dispatch_queue_create(“com.app.task”,NULL)
dispatch_queue_t main = dispatch_get_main_queue();

dispatch_async(queue,^{
 CGFLoat num = [self doSomeMassivecomputation];

 dispatch_async(main,^{
  [self updateUIWithNumber:num];
 });
});

In this bit of code the computation is offloaded onto a background thread with dispatch_async() and then all we need to do is dispatch_async() back into the main queue which will schedule our block to run with the updated data that we computed in the background thread. This is generally the most preferable approach to using grand central dispatch is that it works best with this asynchronous design pattern. If you really need to use dispatch_sync() and absolutely make sure a block has run before going on for some reason,you Could accomplish the same thing with this bit of code

dispatch_sync(queue,^{ num = [self doSomeMassivecomputation]; }); [self updateUIWithNumber:num];

dispatch_sync() works just like dispatch_async() in that it takes a queue as an argument and a block to submit to the queue,but dispatch_sync() does not return until the block you''ve submitted to the queue has finished executing. So in other words the [self updateUIWithNumber:num]; code is guaranteed to not execute before the code in the block has finished running on another thread. dispatch_sync() will work just fine,but remember that Grand Central dispatch works best with asynchronous design patterns like the first bit of code where we simply dispatch_async() back to the main queue to update the user interface as appropriate.

dispatch_apply() dispatch_async() and dispatch_sync() are all okay for dispatching bits of code one at a time,but if you need to dispatch many blocks at once this is inefficient. You Could use a for loop to dispatch many blocks,but luckly GCD has a built in function for doing this and automatically waiting till the blocks all have executed. dispatch_apply() is really aimed at going through an array of items and then continuing execution of code after all the blocks have executed,like so

dispatch_apply(queue,count,^(size_t idx){ do_something_with_data(data,idx); }); //do something with data

This is GCD''s way of going through arrays,you''ll see later on that Apple has added Cocoa API''s for accomplishing this with NSArrays''s,NSSets,etc. dispatch_apply() will take your block and iterate over the array as concurrently as it can. I''ve run it sometimes where it takes the indexes 0,4,6,8 on Core 1 and 1,5,7,9 on Core 2 and sometimes it''s done odd patterns where it does most of the items on 1 and some on core 2,the point being that you don''t kNow how concurrent it will be,but you do kNow GCD will iterate over your array or dispatch all the blocks within the max count you give it as concurrently as it can and then once it''s done you just go on and work with your updated data.

dispatch Groups dispatch Groups were created to group several blocks together and then dispatch another block upon all the blocks in the group completing their execution. Groups are setup very easily and the Syntax isn''t very dissimilar fromdispatch_async(). The API dispatch_group_notify() is what sets the final block to be executed upon all the other blocks finishing their execution.

dispatch_group_t group = dispatch_group_create(); dispatch_group_async(group,queue,^{ NSLog(@"Block 1"); }); dispatch_group_async(group,^{ NSLog(@"Block 2"); }); dispatch_group_notify(group,^{ NSLog(@"Final block is executed last after 1 and 2"); });

Other GCD API you may be Interested in

//Make sure GCD dispatches a block only 1 time
dispatch_once()

//dispatch a Block after a period of time
dispatch_after()

//Print Debugging information
dispatch_debug()

//Create a new dispatch source to monitor low-level System objects
//and automatically submit a handler block to a dispatch queue in response to events.
dispatch_source_create() 

Cocoa & Grand Central dispatch/Blocks

The GCD API''s for being low level API''s are very easy to write and quite frankly I love them and have no problem using them,but they are not appropriate for all situations. Apple has implemented many new API''s in Mac OS X 10.6 SNow Leopard that take advantage of Blocks and Grand Central dispatch such that you can work with existing classes easier & faster and when possible concurrently.

NSOperation and NSBlockOperation NSOperation has been entirely rewritten on top of GCD to take advantage of it and provide some new functionality. In Leopard when you used NSOperation(Queue) it created and killed a thread for every NSOperation object,in Mac OS X 10.6 Now it uses GCD and will reuse threads to give you a nice performance boost. Additionally Apple has added a new NSOperation subclass called NSBlockOperation to which you can add a block and add multiple blocks. Apple has additionally added a completion block method to NSOperation where you can specify a block to be executed upon a NSOperation object completing (goodbye KVO for many NSOperation Objects.)

NSBlockOperation can be a nice easy way to use everything that NSOperation offers and still use blocks with NSOperation.

NSOperationQueue *queue = [[NSOperationQueue alloc] init];
NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
 NSLog(@"Doing something...");
}];

//you can add more blocks
[operation addExecutionBlock:^{
 NSLog(@"Another block");
}];

[operation setCompletionBlock:^{
 NSLog(@"Doing something once the operation has finished...");
}];

[queue addOperation:operation];

in this way it starts to make the NSBlockOperation look exactly like high level dispatch groups in that you can add multiple blocks and set a completion block to be executed.

Concurrent Enumeration Methods

One of the biggest implications of Blocks and Grand Central dispatch is adding support for them throughout the Cocoa API''s to make working with Cocoa/Objective-C easier and faster. Here are a couple of examples of enumerating over a NSDictionary using just a block and enumerating over a block concurrently.

//non concurrent dictionary enumeration with a block
[dict enumerateKeysAndobjectsUsingBlock:^(id key,id obj,BOOL *stop) {
  NSLog(@"Enumerating Key %@ and Value %@",key,obj);
 }];

//concurrent dictionary enumeration with a block
[dict enumerateKeysAndobjectsWithOptions:NSEnumerationConcurrent
    usingBlock:^(id key,BOOL *stop) {
     NSLog(@"Enumerating Key %@ and Value %@",obj);
    }];

The Documentation is a little dry on what happens here saying just "Applies a given block object to the entries of the receiver." What it doesn''t make mention of is that because it has a block reference it can do this concurrently and GCD will take care of all the details of how it accomplishes this concurrency for you. You Could also use the BOOL *stop pointer and search for objects inside NSDictionary and just set *stop = YES; to stop any further enumeration inside the block once you''ve found the key you are looking for.

High Level Cocoa API''s vs Low Level GCD API''s

Chris Hanson earlier wrote about why you should use NSOperation vs GCD API''s. He does make some good points,however I will say that I haven''t actually used NSOperation yet on Mac OS X 10.6 (although I definitely will be using it later on in the development of my app) because the Grand Central dispatch API''s are very easy to use and read and I really enjoy using them. Although he wants you to use NSOperation,I would say use what you like and is appropriate to the situation. I would say one reason I really haven''t used NSOperation is because when GCD was introduced at WWDC,I heard over and over about the GCD API,and I saw how great it was and I can''t really remember NSOperation or NSBlockOperation being talked about much.

To Chris''s credit he does make good points about NSOperation handling dependencies better and you can use KVO if you need to use it with NSOperation Objects. Just about all the things you can do with the basic GCD API''s you can accomplish with NSOperation(Queue) with the same or a minimal couple lines of more code to get the same effect. There are also several Cocoa API that are specifically meant to be used with NSOperationQueue''s,so in those cases you really have no choice but to use NSOperationQueue anyway.

Overall I''d say think what you''ll need to do and why you would need GCD or NSOperation(Queue) and pick appropriately. If you need to you can always write NSBlockOperation objects and then at some point later on convert those blocks to using the GCD API with a minimal amount of effort.

Further Reading on Grand Central dispatch/Blocks

Because I only have so much time to write here,and have to split my time between work and multiple projects,I am linking to people I like who have written some great information about Grand Central dispatch and/or Blocks. Although this article will most definitely not be my last on Grand Central dispatch and/or Blocks.

http://www.friday.com/bbum/2009/08/29/basic-blocks/ http://www.friday.com/bbum/2009/08/29/blocks-tips-tricks/ http://www.mikeash.com/?page=pyblog/friday-qa-2009-08-28-intro-to-grand-central-dispatch-part-i-basics-and-dispatch-queues.html http://www.mikeash.com/?page=pyblog/friday-qa-2009-09-04-intro-to-grand-central-dispatch-part-ii-multi-core-performance.html http://www.mikeash.com/?page=pyblog/friday-qa-2009-09-11-intro-to-grand-central-dispatch-part-iii-dispatch-sources.html

A couple projects making nice use of Blocks

http://github.com/amazingsyco/sscore Andy Matauschak''s KVO with Blocks http://gist.github.com/153676

Interesting Cocoa API''s Making Use of Blocks

A list of some of the Cocoa API''s that make use of blocks (thanks to a certain someone for doing this,really appreciate it.) I should note that Apple has tried not to use the word block everywhere in it''s API for a very good reason. When you come to a new API and you saw something like -[NSArray block] you would probably think it had something to do with blocking using the NSArray or something where you are blocking execution. Although many API do have block in their name,it is by no means the only keyword you should use when looking for API''s dealing with blocks,for these links to work you must have the Documentation installed on your HD.

NSEvent

addGlobalMonitorForEventsMatchingMask:handler:

addLocalMonitorForEventsMatchingMask:handler:

NSSavePanel

beginSheetModalForWindow:completionHandler:

beginWithCompletionHandler:

NSWorkspace

duplicateURLs:completionHandler:

recycleURLs:completionHandler:

NSUserInterfaceItemSearching Protocol

searchForItemsWithSearchString:resultLimit: matchedItemHandler:

NSArray

enumerateObjectsAtIndexes:options:usingBlock:

enumerateObjectsUsingBlock:

enumerateObjectsWithOptions:usingBlock:

indexesOfObjectsAtIndexes:options:passingTest:

indexesOfObjectsPassingTest:

indexesOfObjectsWithOptions:passingTest:

indexOfObjectAtIndexes:options:passingTest:

indexOfObjectPassingTest:

indexOfObjectWithOptions:passingTest:

NSAttributedString

enumerateAttribute:inRange:options:usingBlock:

enumerateAttributesInRange:options:usingBlock:

NSBlockOperation

blockOperationWithBlock:

addExecutionBlock:

executionBlocks

NSDictionary

enumerateKeysAndObjectsUsingBlock:

enumerateKeysAndObjectsWithOptions:usingBlock:

keysOfEntriesPassingTest:

keysOfEntriesWithOptions:passingTest:

NSExpression

expressionForBlock:arguments:

expressionBlock

NSFileManager

enumeratorAtURL:includingPropertiesForKeys: options:errorHandler:

NSIndexSet

enumerateIndexesInRange:options:usingBlock:

enumerateIndexesUsingBlock:

enumerateIndexesWithOptions:usingBlock:

indexesInRange:options:passingTest:

indexesPassingTest:

indexesWithOptions:passingTest:

indexInRange:options:passingTest:

indexPassingTest:

indexWithOptions:passingTest:

NSNotificationCenter

addObserverForName:object:queue:usingBlock:

NSOperation

completionBlock

setCompletionBlock:

NSOperationQueue

addOperationWithBlock:

NSPredicate

predicateWithBlock:

NSSet

objectsPassingTest:

objectsWithOptions:passingTest:

NSString

enumerateLinesUsingBlock:

enumerateSubstringsInRange:options:usingBlock:

CATransaction

completionBlock

c# – Xamarin iOS中的Grand Central Dispatch vs ThreadPool性能

c# – Xamarin iOS中的Grand Central Dispatch vs ThreadPool性能

我已经查看了Xamarin的文档,并建议使用ThreadPool来实现多线程功能,如下所示:

http://docs.xamarin.com/guides/ios/application_fundamentals/threading

但是,已经完成了一项基准测试,表明Grand Central dispatch比ThreadPool更具性能

http://joeengalan.wordpress.com/2012/02/26/execution-differences-between-grand-central-dispatch-and-threadpool-queueuserworkitem-in-monotouch/

因此我的问题是,为什么Xamarin推荐ThreadPool而不是Grand Central dispatch? Xamarin最终是否会将ThreadPool绑定到Grand Central dispatch?什么时候选择一个而不是另一个?因为如果ThreadPool将由Xamarin优化,并最终胜过Grand Central dispatch,那么我不想使用Grand Central dispatch.

解决方法

通过引入更多线程,您可以从机器,特别是移动设备中挤出很少的“额外性能”.

就像我对你所链接的那篇文章的评论(从2012年2月开始)以及你链接的文章的第一段解释了原因.

GCD和ThreadPool之间的区别在于Mono中的ThreadPool具有“慢启动”设置,因此在出现工作峰值时它不会创建超过必要的线程.您可以通过启动太多线程来轻松地使cpu匮乏,因此线程池在创建初始线程之后限制自身,然后尝试每秒仅创建一个新线程(给予或接受,我不记得实际细节).

如果要强制ThreadPool实际启动大量线程,可以使用ThreadPool.SetMinThreads控制它.

使用ThreadPool的原因是相同的代码可以在所有平台上运行.

请注意,该文档讨论了如何使用ThreadPool而不是其他标准.NET线程API,并且没有说明是否使用GCD.仅仅是线程池比使用线程滚动自己的管理更好.

也就是说API,这些天我建议人们使用任务并行库(TPL),这是一种比线程更高层次的思考后台操作的方式.此外,通过切换一行代码,您可以灵活地使用内置线程池或调度到GCD,从而跨平台获得相同的API.

CodeForces - 582A GCD Table (map大数操作&gcd)好题

CodeForces - 582A GCD Table (map大数操作&gcd)好题

CodeForces - 582A
GCD Table
Time Limit: 2000MS   Memory Limit: 262144KB   64bit IO Format: %I64d & %I64u
SubmitStatus

Description

The GCD table G of size n × n for an array of positive integers a of length n is defined by formula

Let us remind you that the greatest common divisor (GCD) of two positive integers x and y is the greatest integer that is divisor of both x and y,it is denoted as

. For example,for array a = {4, 3, 6, 2} of length 4 the GCD table will look as follows:

Given all the numbers of the GCD table G,restore array a.

Input

The first line contains number n (1 ≤ n ≤ 500) — the length of array a. The second line contains n2 space-separated numbers — the elements of the GCD table of G for array a.

All the numbers in the table are positive integers,not exceeding 109. Note that the elements are given in an arbitrary order. It is guaranteed that the set of the input data corresponds to some array a.

Output

In the single line print n positive integers — the elements of array a. If there are multiple possible solutions,you are allowed to print any of them.

Sample Input

Input
4
2 1 2 3 4 3 2 6 1 1 2 2 1 2 3 2
Output
4 3 6 2
Input
1
42
Output
42 
Input
2
1 1 1 1
Output
1 1 

Sample Output

Hint

Source

Codeforces Round #323 (Div. 1)
//题意:输入n,再输入n*n个数
表示给你n个数的gcd表,让你求出这n个数分别是什么。
//思路:
可以将这n*n个gcd的值从小到大排序,再从后往前找,先找到最大的,再根据找到的大的值通过排除法排除掉重复的值,这样一直遍历下去就行了。
Hait:最大的那个数肯定是a[n*n],因为这是它自身与自身的gcd得到的值。因为数很大10^9,所以得用map来计数。
#include<stdio.h>
#include<string.h>
#include<map>
#include<algorithm>
#include<iostream>
#define N 510
using namespace std;
int gcd(int x,int y)
{
	return y==0?x:gcd(y,x%y);
}
map<int,int>m;
int a[N*N],ans[N];
int main()
{
	int n,i,j,k;
	while(scanf("%d",&n)!=EOF)
	{
		m.clear();
		for(i=1;i<=n*n;i++)
		{
			scanf("%d",&a[i]);
			m[a[i]]++;
		}
		sort(a+1,a+n*n+1);
		int top=0;
		for(i=n*n;i>=1;i--)
		{
			if(!m[a[i]])
				continue;
			ans[top++]=a[i];//最大的肯定是自身与自身的gcd 
			m[a[i]]--;
			for(j=0;j<top-1;j++)
				m[gcd(ans[j],a[i])]-=2;//由表可知,它是对称的,所以 要减去2 
		}
		for(i=0;i<top;i++)
			printf("%d ",ans[i]);
		printf("\n");
	}
	return 0;
}

关于Swift - 多线程实现方式3 - Grand Central Dispatch的介绍已经告一段落,感谢您的耐心阅读,如果想了解更多关于2017CCPC 杭州 J. Master of GCD【差分标记 / 线段树 / GCD】、A Guide to Blocks & Grand Central Dispatch (and the Cocoa API's making use of them)、c# – Xamarin iOS中的Grand Central Dispatch vs ThreadPool性能、CodeForces - 582A GCD Table (map大数操作&gcd)好题的相关信息,请在本站寻找。

本文标签: