Grand Central Dispatch (GCD)是异步执行任务的计数之一。一般讲应用程序中计数的线程管理用的代码在系统级中实现。开发者只需要定义想执行的任务并追加到适当的Dispatch Queue中,GCD就能生成必要的线程并计划执行任务。由于线程管理是作为系统的一部分来实现的,因此可统一管理,也可执行任务,这样就比以前的线程更有效率。
Dispatch Queue :执行处理的等待队列,采用 FIFO(先进先出)的原则。
我们可以通过系统提供的主队类、全局队列或者自定义队列获取队列使用。
Main Dispatch Queue本质是一个特殊的串行队列,主队列的任务都在主线程来执行,专门负责调度主线程度的任务,无法开辟新的线程。所以,在主队列下的任务不管是异步任务还是同步任务都不会开辟线程,任务只会在主线程顺序执行。如果在主线程上已经有任务正在执行,主队列会等到主线程空闲后再调度任务。
获取方式:
dispatch_queue_t mainDispatchQueue = dispatch_get_main_queue();
Global Dispatch Queue 是所有用用程序都能够使用的并行队列。全局队列默认有4个执行优先级:高优先级(High Priority)、默认优先级(Default Priority)、低优先级(Low Priority)、后台优先级(Background Priority)。
获取方式:
dispatch_queue_t globalDispatchQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
使用 dispatch_queue_create(const char *_Nullable label, dispatch_queue_attr_t _Nullable attr方法来创建队列。该方法传入两个参数:
第一个参数要附加到队列的字符串标签,可为NULL。
第二个参数为队列属性,识别是串行队列还是并发队列。DISPATCH_QUEUE_SERIAL 为串行队列,DISPATCH_QUEUE_CONCURRENT为并发队列。
//串行队列
dispatch_queue_t serialQueue = dispatch_queue_create("com.test.serialQueue", DISPATCH_QUEUE_SERIAL);
//并行队列
dispatch_queue_t concurrentQueue = dispatch_queue_create("com.test.concurrentQueue", DISPATCH_QUEUE_CONCURRENT);
同步添加任务到指定的队列中,在添加的任务执行结束之前,会一直等待,直到队列里面的任务完成之后再继续执行。
只能在当前线程中执行任务,不具备开启新线程的能力。
dispatch_sync(queue, ^{
});
异步添加任务到指定的队列中,它不会做任何等待,可以继续执行任务。
可以在新的线程中执行任务,具备开启新线程的能力。
dispatch_async(queue, ^{
});
同步任务优先级高,在线程中有执行顺序,不会开启新的线程。
异步任务优先级低,在线程中执行没有顺序,看cpu闲不闲。在主队列中不会开启新的线程,其他队列会开启新的线程。
dispatch_queue_t concurrentQueue = dispatch_queue_create("concurrentQueue", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(concurrentQueue, ^{
NSLog(@"1");
});
dispatch_sync(concurrentQueue, ^{
NSLog(@"2");
});
输出结果:
2
1

主队列中的任务一定在主线程执行,在主线程中执行的任务不一定来至主队列。
在主队列开启异步任务,不会开启新的线程而是依然在主线程中执行代码块中的代码。为什么不会阻塞线程?
主队列开启异步任务,虽然不会开启新的线程,但是他会把异步任务降低优先级,等闲着的时候,就会在主线程上执行异步任务。
并行队列里开启同步任务不会开辟新的线程,顺序执行;只有异步才会开启新的线程,任务没有固定执行顺序
串行队列开启异步任务,会开辟一条新的线程,任务顺序执行
串行队列开启异步任务后嵌套同步任务造成死锁
dispatch_queue_t serialQueue = dispatch_queue_create("com.test.serialQueue", DISPATCH_QUEUE_SERIAL);
dispatch_async(serialQueue, ^{
NSLog(@"异步任务%@", [NSThread currentThread]);
//下面开启同步造成死锁:因为串行队列中线程是有执行顺序的,需要等上面开启的异步任务执行完毕,才会执行下面开启的同步任务。而上面的异步任务还没执行完,要到下面的大括号才算执行完毕,而下面的同步任务已经在抢占资源了,就会发生死锁。
dispatch_sync(serialQueue, ^{
NSLog(@"同步任务%@", [NSThread currentThread]);
});
});
dispatch_queue_t serialQueue = dispatch_queue_create("com.test.serialQueue", DISPATCH_QUEUE_SERIAL);
dispatch_sync(serialQueue, ^{
NSLog(@"同步任务%@", [NSThread currentThread]);
//下面开启同步造成死锁:因为串行队列中线程是有执行顺序的,需要等上面开启的同步任务执行完毕,才会执行下面开启的同步任务。而上面的同步任务还没执行完,要到下面的大括号才算执行完毕,而下面的同步任务已经在抢占资源了,就会发生死锁。
dispatch_sync(serialQueue, ^{
NSLog(@"同步任务%@", [NSThread currentThread]);
});
});
dispatch_queue_t serialQueue = dispatch_queue_create("com.test.serialQueue", DISPATCH_QUEUE_SERIAL);
dispatch_sync(serialQueue, ^{
NSLog(@"同步任务%@", [NSThread currentThread]);
dispatch_async(serialQueue, ^{
NSLog(@"异步任务%@", [NSThread currentThread]);
});
});
请注意,队列不是线程!单个队列可以为多个工作线程提供服务,反之亦然。
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
dispatch_sync(dispatch_get_main_queue(), ^{
[self doSomething];
});
}

主队列中提交viewDidLoad任务之后提交一个blcok任务,但无论哪一个任务都要分配到主线程执行。现在分配的viewDidLoad在主线程中处理时在其执行过程中需要调用block任务,当block同步调用执行完成之后viewDidLoad方法才能继续执行,所以viewDidLoad的调用结束需要依赖后续提交的block任务,而根据队列的先进先出原则block任务执行需要等待viewDidLoad执行完成才能执行,因此产生了相互等待,引起死锁。
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
dispatch_queue_t serialQueue = dispatch_queue_create("com.test.serialQueue", DISPATCH_QUEUE_SERIAL);
dispatch_sync(serialQueue, ^{
[self doSomething];
});
}
此时viewDidLoad提交到主队列,block提交到自定义串行队列。
viewDidLoad在主队类执行时会在主线程执行,执行过程中需要同步提交一个block任务至串行队列,此时串行队列中的block任务是同步提交则最终任务会在主线程中执行,当block任务在主线程中执行完成之后,继续执行主队列中viewDidLoad后续任务。
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
dispatch_queue_t globalDispatchQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
NSLog(@"1");
dispatch_sync(globalDispatchQueue, ^{
NSLog(@"2");
dispatch_sync(globalDispatchQueue, ^{
NSLog(@"3");
});
NSLog(@"4");
});
NSLog(@"5");
}
结果:12345
同步提交任务不会开辟新线程。首先输出log1,此时通过同步方式提交一个任务至全局并发队列,其任务在主线程执行,输出log2。之后在block中又提交了一个同步任务至全局并行队列(并行队列特点就是提交至并发队列中的所有任务都可以并发执行,此时同步提交的任务不影响上一个未执行完的任务),输出log3,之后一次输出log4,log5。
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
dispatch_queue_t globalDispatchQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(globalDispatchQueue, ^{
NSLog(@"1");
[self performSelector:@selector(printLog) withObject:nil afterDelay:0];
NSLog(@"3");
});
}
- (void)printLog {
NSLog(@"2");
}
输出结果:13
iOS 多线程:『GCD』详尽总结
《Objective-C高级编程-iOS与OS X多线程和内存管理》
Region是HBase数据管理的基本单位,region有一点像关系型数据的分区。region中存储这用户的真实数据,而为了管理这些数据,HBase使用了RegionSever来管理region。Region的结构hbaseregion的大小设置默认情况下,每个Table起初只有一个Region,随着数据的不断写入,Region会自动进行拆分。刚拆分时,两个子Region都位于当前的RegionServer,但处于负载均衡的考虑,HMaster有可能会将某个Region转移给其他的RegionServer。RegionSplit时机:当1个region中的某个Store下所有StoreFile
昨晚看到IDEA官推宣布IntelliJIDEA2023.1正式发布了。简单看了一下,发现这次的新版本包含了许多改进,进一步优化了用户体验,提高了便捷性。至于是否升级最新版本完全是个人意愿,如果觉得新版本没有让自己感兴趣的改进,完全就不用升级,影响不大。软件的版本迭代非常正常,正确看待即可,不持续改进就会慢慢被淘汰!根据官方介绍:IntelliJIDEA2023.1针对新的用户界面进行了大量重构,这些改进都是基于收到的宝贵反馈而实现的。官方还实施了性能增强措施,使得Maven导入更快,并且在打开项目时IDE功能更早地可用。由于后台提交检查,新版本提供了简化的提交流程。IntelliJIDEA
介绍pytest是一个非常成熟的全功能的Python测试框架,主要有以下几个特点:简单灵活,容易上手支持参数化能够支持简单的单元测试和复杂的功能测试,还可以用来做selenium/appnium等自动化测试、接口自动化测试(pytest+requests)pytest具有很多第三方插件,并且可以自定义扩展,比较好用的如pytest-selenium(集成selenium)、pytest-html(完美html测试报告生成)、pytest-rerunfailures(失败case重复执行)、pytest-xdist(多CPU分发)等测试用例的skip和xfail处理可以很好的和jenkins集成
📝学技术、更要掌握学习的方法,一起学习,让进步发生👩🏻作者:一只IT攻城狮。💐学习建议:1、养成习惯,学习java的任何一个技术,都可以先去官网先看看,更准确、更专业。💐学习建议:2、然后记住每个技术最关键的特性(通常一句话或者几个字),从主线入手,由浅入深学习。❤️《SpringCloud入门实战系列》解锁SpringCloud主流组件入门应用及关键特性。带你了解SpringCloud主流组件,是如何一战解决微服务诸多难题的。项目demo:源码地址👉🏻SpringCloud入门实战系列不迷路👈🏻:SpringCloud入门实战(一)什么是SpringCloud?SpringCloud入门实战
文章目录一,什么是kaliPurle(卡利紫)二,如何安装kaliPurple。(有步骤没图片直接是默认)1,复制它的下载链接到迅雷可以让你下镜像变得更快。2,打开你的虚拟机创建新的虚拟机3,点击后面浏览然后找到镜像的所在地选中确定,下一步4,这里默认就可以,因为Ubuntu和这个差不多架构。5,然后,名字自己改一下,然后把他安到你想要装的盘,容量默认。之后一直下一步就可以**6,打开它,然后第一个图形界面安装,直接回车,然后选中文点continue之后没有图片的直接点继续。7,密码想设什么设什么。然后一直继续到我的图片那里改一下就可以了。8,软件默认就行。9,耐心等待。然后点手动配置dvc然
目录关于MPU6050芯片关于小板关于厂家和DATASHEET关于漂移关于角加速度还是角速度关于精度和量程(可调,可选)关于功耗,陀螺仪+加速器工作电流:3.8mA(全功率,陀螺仪在所有速率下,在1kHz采样率下加速)采样率高,功耗也高可以参考 MPU6050陀螺仪与Processing和匿名上位机飞控联动实录-知乎关于MPU6050芯片MPU6050传感器模块是6轴运动跟踪设备。包含3轴陀螺仪、3轴加速度计、运动处理器、温度传感器。I2C总线接口,可与微控制器进行通信。通过辅助I2C总线与其他传感器设备通信,如3轴磁力计、压力传感器等。如果3轴磁力计连接到辅助I2C总线,则MPU6050可
MySQL为您提供了一个有用的字符串函数REPLACE(),它允许您用新的字符串替换表的列中的字符串。REPLACE()函数的语法如下:REPLACE(str,old_string,new_string);SQLREPLACE()函数有三个参数,它将string中的old_string替换为new_string字符串。注意:有一个也叫作REPLACE的语句用于插入或更新数据。所以不要将REPLACE语句与这里的REPLACE字符串函数混淆。REPLACE()函数非常方便搜索和替换表中的文本,例如更新过时的URL,纠正拼写错误等。在UPDATE语句中使用REPLACE函数的语法如下:UPDATE
SM4为分组对称密码算法,明文、密文以及密钥长度均为128128128bits。SM4算法主要包括加解密算法和密钥扩展算法,采用323232轮非线性迭代的数学结构,其中算法中每一次迭代运算为一轮非线性变换。主要操作包括异或、合成置换、非线性迭代、反序变换、循环移位以及S盒变换等。加密算法和解密算法的数学架构、运算法则、运算操作等都是完全相同的,解密运算只需要将加密算法中生成的轮密钥进行反序使用。其流程图如下图所示。图1.SM4密码算法加密流程图密钥扩展算法 设加密主密钥MK=(MK0,MK1,MK2,MK3)MK=(MK_0,MK_1,MK_2,MK_3)MK=(MK0,MK1,MK
前言本文为Json简介与基本使用相关知识,下边具体将对什么是JSON,XML与JSON的区别,JSON的语法格式,JSON数据的转换(包括:Java对象转换为JSON格式、JSON格式转换为Java对象)等进行详尽介绍~📌博主主页:小新要变强的主页👉Java全栈学习路线可参考:【Java全栈学习路线】最全的Java学习路线及知识清单,Java自学方向指引,内含最全Java全栈学习技术清单~👉算法刷题路线可参考:算法刷题路线总结与相关资料分享,内含最详尽的算法刷题路线指南及相关资料分享~👉Java微服务开源项目可参考:企业级Java微服务开源项目(开源框架,用于学习、毕设、公司项目、私活等,减少
这个赛题的训练数据其实和去年是一样的,只是是语义分割的评价指标改成了类似实例分割的指标。1.赛道背景变化检测对“耕地红线”、土地利用监管等应用具有重要意义。利用多时相遥感数据,采用多种图像处理和模式识别方法提取变化信息,并定量分析和确定地表变化的特征与过程,便是遥感变化检测的本质。传统遥感行业基于人工两期影像标注从而判别地物时相变化的方法受限于效率低、成本高等问题,难以满足实际应用需求,本赛道希望遴选出高效的遥感图像变化检测算法模型,对图像中的变化图斑信息进行高效识别,提高空间信息网络建设中遥感图像快速变化识别能力。2.赛道任务变化检测赛道力求对通过前后两时相的遥感影像,提取出地物发生变化的斑