月度归档: 2021 年 3 月

这一次,阿里云再度将“重构计算”扛在肩头!

引言:冲击业务永续与*致性能,推进自研软硬一体与全面云原生,阿里云这是要将“重构计算”进行到底了……

近日,阿里云第三代神龙云服务器风风火火的上新了。

这一幕距离六月基础设施算力升级,搭载第三代神龙云服务器架构的高主频七代发布仅仅过了一个多月。

阿里云弹性计算负责人旭卿说,如此之快还要归功于第三代神龙架构带来的利好尝试。

确实,通过三代神龙架构的强势助力,全新推出的第三代神龙云服务器在各项服务能力上都得到了全面升级。

无论是计算效率还是网络与存储方面的硬实力,均可谓“强势来袭”。

综合性能暴涨160%,第三代神龙云服务器不是一点子智慧
有数据显示,与上一代神龙云服务器同款相比,这次的三代产品综合性能暴涨高达160%,相比目前全球范围内*顶级的云服务器还要快上超过30%,地表强悍有木有?

与第七代ECS企业级高主频实例类似,第三代神龙云服务器在架构上更好地支持了一些四路服务器。

或许大家可能知晓,主流的云服务器过去通常采用的是二路服务器,即一个服务器中携带两颗CPU。

如今创新性选择了更加高密度部署的四路服务器制式,也就是同时携带四颗CPU。不但是单体计算性能得到显著提升,从整机的性能角度上也有很大飞跃。

很明显,四路服务器带来的好处,每颗均摊到整体基础设施的成本,相比之前确实下降不少,当然这也是其整体性能综合提升高达160%的关键所在。

具体来说,第三代神龙云服务器产品家族提供了*多208核、*大6TB内存。

其中云盘IOPS高达 100万、2400万的网络转发以及*高达100G的网络带宽,掐指一算均为全球*高性能水平。

如此表现出挑,根源何处?

旭卿认为第三代神龙架构中的自研神龙芯片很关键。

以云盘IOPS为例,经过阿里云整体性能测试,即便是达到峰值100万的状态,其表现出的延迟也基本呈直线状态,充分说明其性能平稳异于非常。

%title插图%num

 

这主要得益于在架构层面被提供了硬件的QoS能力,其统计的精确程度是传统云盘或者软件层面无法比拟的。

当然,怎样能够在快速互联网迭代方式下,能够解决芯片伴随用户周期迭代,并同时确保稳定性能等,这些统统都提出了很大挑战。

总体来说,在三代神龙架构的推动下,神龙芯片在数据面的加速以及硬件QoS能力上为云服务器以及第六代ECS增强型实例提供了强有力的保障。

如果说进一步提及第三代神龙云服务器的场景优势,“全能选手”或可称为关键词之一。

对此科技星象获悉,在一些通用类的业务中,该产品带来的优势提升表现明显。例如在以持久内存著称的AEP实例中,经常运行的SAP Hana数据库场景、缓存Redis场景以及AI领域经常提及的参数服务器场景中,性能表现都很突出。
%title插图%num

此外,值得强调的一点子智慧,第三代神龙云服务器产品家族还支持CPU、GPU、NPU、FPGA等多种计算形态,具备3分钟交付50万核vCPU的*速扩容能力,被称为云原生的*佳载体。

用旭卿的话说,这就是一款真正的云原生硬件。

谈及这个概念自然免不了说说“买神龙服务器”的梗。

神龙服务器上新之初,的确有很多人纷纷跑来咨询买入并打算在线下使用。

其实回复很简单,神龙服务器很难在线下使用。原因在于其与云计算的结合度很高,并不是一台“拿回家就可以使用”的服务器。

而是需要与阿里云庞大有力的基础设施相融合,通过软硬件协同才能有效发挥*致性能。

如果独立拿出一个硬件使用,对于企业软件的开发成本可谓是增加了更多不必要的负担。
%title插图%num

当然,神龙服务器的“云原生属性”不单单表现在与云计算使用的紧密结合,更重要的是与容器的“天生一对”。

过去人们总认为容器的*佳CP是物理服务器,但其实忽视了几个属于物理服务器的天生缺陷,例如无弹性、不稳定、共性连困难以及迭代速度缓慢等。

而基于神龙架构的云服务器,既具备传统物理机的*佳性能又兼具虚拟机的灵活性。

由于在虚拟化技术中采用了硬件隔离的方式,使服务器的安全性也很高,并且将存储、网络的IO运算封装在芯片中,果断实现了端到端安全。

再加上阿里云本身的迭代周期完全可以达到*快达每周一更新,远远超过了传统意义上半年一迭代的速率。

更重要的是,神龙架构对云原生浪潮下容器等产品适配程度*高。

通过I/O offload芯片加速,高效调度和自动化弹性伸缩的容器化产品可帮助降低50%的计算成本,性能甚至比物理机更优越。

举个例子来说,在典型的双十一场景中,压测过程中我们就会发现,神龙服务器和同规格的物理机相比,在云原生的应用场景下性能会有20%到30%的性能提升。

通常情况下,传统物理机性能在压测中能够达到40%-50%的CPU利用率就已堪称*限,可见与神龙服务器的差异性之大。

第六代增强型实例入驻ECS产品家族,多几个九那都是小事儿
另外在发布中,基于第三代神龙云服务器以及架构,阿里云还构建了新一代ECS产品家族。

其中包括六月初刚刚邀测的第七代高主频实例,以及内存增强硬实例,新一代GPU实例与NPU实例,还涉及超级计算集群实例,非易失性内存APE实例等在内。

在不断扩展服务用户的能力同时,基于第三代神龙云服务器架构的第六代增强型实例也被顺势妥妥纳入其中。

值得提及的一点,该实例由三部分组成,在计算方面阿里云率先自研了Dragonfly Hypervisor,不再使用传统例如KVM、XEN这种虚拟化架构。

除了具备非常轻量级的特性,Dragonfly Hypervisor不仅资源占用少,还在虚拟化效率提升上收效明显。

据悉可以在计算抖动层面做到百万分之一的级别。

此外全系搭配ESSD系列云盘,存储转发能力*多提升四倍。

进一步了解,过去三年间,阿里云方面一直致力于打造新一代SSD云盘。

而通过ESSD可以具备单盘100万IOPS能力,单路延迟*低可以做到100微秒,每一次快照备份可以做到5秒钟之内。

这样一种*致性能,其实大大提升了第六代增强型实例的存储能力。

有数据显示,ESSD还支持10Gbps突发内网带宽,单卷延时大幅下降;性能等级按需配置,在线无损变配,同时使用门槛大幅下降50%。

在网络能力方面,自研的神龙架构也带来了超强网络IO能力,*强可以提供单实例2400万PPS的转发能力。

这就意味着,每个数据包*低延迟可以做到21us。

更重要的是,Mysql和Redis性能提升超过15%,Nginx性能提升达100%。

配合Alibaba Cloud Linux 2 LTS,启动速度*多提升60%,运行时性能提升30%以上且稳定性*多提升50%。

可以说第六代增强型实例算是集大成者,果断继承了第三代神龙云服务器的几乎所有优点。

过去的一个多月的时间,已有超过80%的用户开始使用第六代增强型实例,如今已全球开售。

另外针对内存密集型的应用,例如SAP HANA内存数据库应用,本次发布也推出了业界首款裸金属且经过SAP HANA认证的实例。

实例本身具备208vCPU和*高6个TB内存,无论是支撑OLTP还是OLAP,与传统物理机以及上一代产品相比,都会有35%以上的性价比提升。

“除此之外,安全可信云实例其实也是基于我们对于硬件、固件和操作系统全栈的安全能力基础上推出的可信实例。”

以弹性计算服务为例,阿里云透露,目前单实例的可用性可以做到99.975%;而跨可用区多实例可用性也可做到99.995%。
%title插图%num

总之通过技术和产品创新,提供更高的可靠性、可用性的能力才是关键。

对此阿里云弹性计算负责人旭卿表示,传统服务器主要依赖堆砌硬件提升性能;而阿里云自研的神龙架构更多基于硬件云原生理念,创新性打破了虚拟化技术与CPU、内存、网卡等硬件的天然鸿沟,可发挥出比传统物理机更强的性能。

我们理解,尽管摩尔定律客观左右发展,但通过软硬一体化的思路确实可以将软硬结合的性能潜力激发出来,达成“超摩尔”的效果。

毕竟阿里云就是此工作成功的实践者之一。

关于未来,旭卿坦承,对于神龙架构的存储性能提升、安全合规增强以及SOC方面的规划都会成为继续努力的技术升级方向。

十年进化,重构计算:业务永续+性能*致,一直都是标准旋律
一直以来,云计算被誉为新的计算模式,其弹性计算服务作为*基础核心的产品被业界熟知。

基于此,2010年5月10日,阿里云对外发布的*个商业化的产品就是弹性计算产品,也就是ECS1.0。

从2010年通过发布ECS1.0来服务中小企业站长,到2015年发布ECS2.0来服务诸如12306这种*具挑战的业务场景,再到2017-2018年,上马神龙架构去承担双11这种世界级的难题。

“经过十年进化,我们确实重构了整个计算的服务模式,也具备了服务全业务场景的能力。”

有数据统计,过去十年时间,阿里云的存储性能提升了2000倍,网络性能提升了500倍,整体算力以平均每12个月翻一番的速度增长。

但归于根本,都是为了满足用户*重要的诉求之一,那就是业务永续,即业务永远不要停机、不要宕机。

“一直以来,阿里云都始终坚持自主研发,我们挑剔和控制掌握每一行代码,就是做到为用户提供更加稳定与可靠的服务,保障永不停机的计算服务,是我们的使命。”

这是2019年杭州云栖大会上,阿里巴巴合伙人、阿里云智能基础产品事业部总经理、研究员蒋江伟,花名小邪的压轴之词。

当然在业务永续的基础之上,*致性能的要求更是重中之重。

在过去几年间,阿里云借着软硬一体化的趋势,自研了神龙计算平台、盘古存储平台和洛神网络平台,通过软硬一体化的结合能力来大幅度提升计算效率。

早在2016年阿里云就秘密启动了一项代号为“X-Dragon”的项目,并于2017年推出首款自研神龙云服务器,就独自研发解决方案并重构了云计算的基础设施。

而*新发布的第三代自研神龙架构,更是贯穿了整个IaaS计算平台,并在 IOPS、PPS 等方面提升5倍性能,甚至可以做到在云上获得物理机100%的计算能力。

如今从*早的单一通用计算,到推出异构计算与高性能计算产品,再到目前一系列新品出炉,阿里云弹性计算已覆盖互联网、金融、零售等行业在内的近300种场景,全球22个地域,63个大型的数据中心支撑各种流量高峰。例如12306的春运抢票、微博热点暴涨流量以及钉钉2小时扩容10万台云服务器等。

目前架构已大规模应用于淘宝、天猫、菜鸟等业务,高效解决高峰值的性能瓶颈问题。

据悉以“帮助中小企业更快更好上云,在疫情期间节约IT成本渡过难关”为主题的“以旧换新,10亿元补贴”计划与“培养更多云计算高级人才助力技术产业发展”的高校计划为达成进一步的神龙生态发展,已纷纷启动。

而伴随云计算向纵深方向发展,软硬一体和云原生将成为云计算技术架构的主流。

肉眼可见,阿里云正通过不断推进软硬一体化与全方位云原生化来加快重构基础设施计算层面,这是铁定的主旋律,不过对此,你看好吗?

python基础篇(三)

python基础篇(三)
这篇主要整理pandas常用的基本函数,主要分为五部分:

汇总函数
特征统计函数
唯一值函数
替换函数
排序函数
1、汇总函数
常用的主要是4个:

tail(): 返回表或序列的后n行
head(): 返回表或序列的前n行
info(): 返回表的信息概况
describe(): 返回表中数值列对应的主要统计量
n默认为5
df.describe()

#运行截图
Height Weight
count 183.000000 189.000000
mean 163.218033 55.015873
std 8.608879 12.824294
min 145.400000 34.000000
25% 157.150000 46.000000
50% 161.900000 51.000000
75% 167.500000 65.000000
max 193.900000 89.000000

2、特征统计函数
在Series和DataFrame上定义了许多统计函数,*常见的是:

sum
mean (均值)
median (中位数)
var (方差)
std (标准差)
max
min
用法示例
df_demo = df[[‘Height’, ‘Weight’]]
df_demo.mean()
1
2
聚合函数
quantile (返回分位数)
count (返回非缺失值个数)
idxmax (*大值对应的索引)
聚合函数,有一个公共参数axis,axis=0代表逐列聚合,axis=1表示逐行聚合

df_demo.mean(axis=1).head()
1
3、唯一值函数
唯一值函数常用的四个函数:

unique() : 得到唯一值组成的列表->统计出指定列唯一存在的值有哪些
nunique() :唯一值的个数->统计出指定列唯一存在的值总共有多少个
value_counts() : 得到唯一值和其对应出现的频数
drop_duplicates() : 去重
duplicated()
drop_duplicates()基本用法
关键参数keep
first : 保留*次出现的重复行,删除后面的重复行
last : 删除重复项,除了*后一次出现
False:把所有重复组合所在的行剔除。
需要指定列
代码:

#原本的数据样例
df_demo = df[[‘Gender’,’Transfer’,’Name’]]
df_demo

Gender Transfer Name
0 Female N Gaopeng Yang
1 Male N Changqiang You
2 Male N Mei Sun
3 Female N Xiaojuan Sun
4 Male N Gaojuan You
… … … …
195 Female N Xiaojuan Sun
196 Female N Li Zhao
197 Female N Chengqiang Chu
198 Male N Chengmei Shen
199 Male N Chunpeng Lv
200 rows × 3 columns

#现给Gender,Transfer两列去重
df_demo.drop_duplicates([‘Gender’,’Transfer’])

Gender Transfer Name
0 Female N Gaopeng Yang
1 Male N Changqiang You
12 Female NaN Peng You
21 Male NaN Xiaopeng Shen
36 Male Y Xiaojuan Qin
43 Female Y Gaoli Feng

由此可见,使用了first参数,保留*次出现的重复行,删除后面的重复行
在未指定参数的情况下,keep默认first;

指定last
案例如下:

df_demo.drop_duplicates([‘Gender’, ‘Transfer’], keep=’last’)
1
Gender Transfer Name
147 Male NaN Juan You
150 Male Y Chengpeng You
169 Female Y Chengquan Qin
194 Female NaN Yanmei Qian
197 Female N Chengqiang Chu
199 Male N Chunpeng Lv

last:删除所有的重复行,只保留出现的*后一个
drop_duplicates() & duplicated()的区别
duplicated和drop_duplicates的功能类似,但前者返回了是否为唯一值的布尔列表,其keep参数与后者一致。其返回的序列,把重复元素设为True,否则为False。 drop_duplicates等价于把duplicated为True的对应行剔除。
4、替换函数
替换函数有三类:

映射函数:replace()…
逻辑函数:(1)where (2)mask
数值替换
replace的用法
#原本的数据
df_demo = df[[‘Gender’,’Transfer’,’Name’]]
df_demo

Gender Transfer Name
0 Female N Gaopeng Yang
1 Male N Changqiang You
2 Male N Mei Sun
3 Female N Xiaojuan Sun
4 Male N Gaojuan You
… … … …
195 Female N Xiaojuan Sun
196 Female N Li Zhao
197 Female N Chengqiang Chu
198 Male N Chengmei Shen
199 Male N Chunpeng Lv
200 rows × 3 columns
1
#替换Gender,女替换为0,男替换为1
df[‘Gender’].replace({‘Female’:0, ‘Male’:1}).head()

Name: Gender, dtype: int64

逻辑替换
逻辑替换包括了where和mask,这两个函数是完全对称的:where函数在传入条件为False的对应行进行替换,而mask在传入条件为True的对应行进行替换,当不指定替换值时,替换为缺失值(NAN)

s = pd.Series([-1, 1.2345, 100, -50])
s.where(s<0)

0 -1.0
1 NaN
2 NaN
3 -50.0
dtype: float64

s.where(s<0, 100)

0 -1.0
1 100.0
2 100.0
3 -50.0
dtype: float64

s.mask(s<0)

0 NaN
1 1.2345
2 100.0000
3 NaN
dtype: float64

centos 下 nginx 使用了 HTTPs,网页访问不了

周一之前 https 可以正常访问,周一之后就不行。问了阿里云那边,阿里云那里可以正常访问。服务器端口都开放了,没有防火墙。域名由于法人更换,有段时间是不行的。现在 80 端口可以访问,就是 443 端口出问题了。切换端口也可以。这是什么问题啊?

tomwen 1
tomwen 2019-12-31 09:55:11 +08:00
域名能发出来看看吗?
首先端口是不是开了?不能访问是浏览器阻止了还是直接就打不开?是不是证书过期或者自制证书?
guanganqishi 2
guanganqishi 2019-12-31 10:21:35 +08:00 ❤️ 1
@tomwen kubao.360reborn.com:8443 弄了个 8443 端口可以访问 https://kubao.360reborn.com 443 端口不能访问
证书是昨天弄了新的,还是不行。浏览器显示的是连接已重置
sujin190 3
sujin190 2019-12-31 10:52:30 +08:00
香港阿里云的话,一直都有这个问题啊,tsl 连接会被阻断,过几分钟又正常了
guanganqishi 4
guanganqishi 2019-12-31 11:01:44 +08:00
@sujin190 不是香港的,服务器在杭州
ChicC 5
ChicC 2019-12-31 11:04:45 +08:00
配置问题咯
guanganqishi 6
guanganqishi 2019-12-31 11:08:26 +08:00
@ChicC
server {
listen 443 ssl http2;
listen [::]:443 ssl;
server_name *.360reborn.com;
charset utf-8;
access_log logs/kubao.https.access.log main;
error_log logs/kubao.https.error.log error;

index index.php index.html index.htm;

ssl on;
ssl_certificate /usr/local/nginx/ssh/360reborn.pem;
ssl_certificate_key /usr/local/nginx/ssh/360reborn.key;

ssl_session_cache shared:SSL:10m;
ssl_session_timeout 5m;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP;
ssl_prefer_server_ciphers on;

location / {
root /var/www/kubao/web;
index index.php index.html index.htm;
if (!-e $request_filename) {
rewrite ^(.*)$ /index.php?s=$1 last;
break;
}
}

error_page 404 /404.html;

error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}

location ~ \.php$ {
root /var/www/kubao/web;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}

}

是这样的配置
sujin190 7
sujin190 2019-12-31 11:17:49 +08:00
看了下,tls 就建立不成功,客户端发送 client hello 之后连接被服务器重置了,但是不发送域名是可以成功建立连接的,所以要么是域名备案问题,要么是防火墙有特殊配置,实在不行也可以升级下 nginx 和 openssl 试试
sujin190 8
sujin190 2019-12-31 11:19:08 +08:00
证书和加密套件配置都没有问题,如果域名备案没有问题,防火墙也是正常的,那么 nginx 有 bug 也是可能的
guanganqishi 9
guanganqishi 2019-12-31 11:43:46 +08:00
@sujin190 嗯嗯 好的 谢谢 我再看看吧
sujin190 10
sujin190 2019-12-31 11:53:08 +08:00
看非 443 可以正常用而且是服务器 rst,所以大概率是域名合规问题,实在找不出啥问题可以给阿里云提工单问问

noqwerty 2019-12-31 12:02:30 +08:00 via Android
我这边可以直接打开你的链接啊,浏览器清一下缓存看看?
venhow 12
venhow 2019-12-31 14:33:46 +08:00
没有加载到证书啊
ChicC 13
ChicC 2019-12-31 14:42:46 +08:00
ssl_certificate /usr/local/nginx/ssh/360reborn.pem;
@guanganqishi

是配置 pem 文件吗?不是 crt 吗
justfly 14
justfly 2019-12-31 14:49:37 +08:00
https://47.98.153.226/ 没问题,也能达到正确的证书,所以倾向于证书没啥问题,但是使用域名就有问题,怀疑防火墙或者 SNI 相关逻辑,看看 nginx 的错误日志。
privil 15
privil 2019-12-31 15:10:37 +08:00
本机配置一下 host 域名指向 127.0.0.1 然后 curl 试一下行不行。
privil 16
privil 2019-12-31 15:11:25 +08:00
服务器本机。
jeblur 17
jeblur 2019-12-31 15:16:41 +08:00
正常打开
whnzy 18
whnzy 2020-01-03 16:38:24 +08:00
法人变更,是需要更新备案信息的,因为 2020 年,TLSv1.0 和 TLSv1.1 就不支持了,TLSv1.2 是支持 SNI 的,很容易被监测出来的。
我 ICP 查询,你们是备案的,但是有可能是因为没有更新备案信息。
每个浏览器对 TLSv1.0 和 TLSv1.1 的禁用时间不同,就会导致不同的浏览器会有不同的表现。
希望能帮到你。

python爬虫–协程

python爬虫–协程
基本知识
event_loop:事件循环,相当于一个无限循环,我们可以把一些函数注册到这个事件循环上,当满足某些条件的时候,函数就会被循环执行。
coroutine:携程对象,我们可以将携程对象注册到事件循环中,它会被时间循环调用。我们可以使用async关键字来定义一个方法,这个方法在调用时不会被立即执行,而是返回一个协程对象。
task:任务,它是对协程对象的进一步封装, 包含了任务的各个状态。
future:代表将来执行或还没有执行的任务,实际上和task 没有本质区别。
async定义-个协程.
await用来挂起阻塞方法的执行。
协程的基本使用
import asyncio

async def request(url):
print(‘正在请求的url是:’,url)
print(‘请求成功:’,url)
#async修饰的函数,调用之后返回的一个协程对象
c = request(‘www.baidu.com’)

# #创建一个事件循环对象
# loop = asyncio.get_event_loop()
#
# #将携程对象注册到loop中,然后启动loop
# loop.run_until_complete(c)

# #task的使用
# loop = asyncio.get_event_loop()
# #基于loop创建一个task对象
# task = loop.create_task(c)
# print(task)
# loop.run_until_complete(task)
# print(task)

#future的使用
loop = asyncio.get_event_loop()
task = asyncio.ensure_future(c)
print(task)
loop.run_until_complete(task)
print(task)

多任务协程实现
import asyncio
import time

async def request(url):
print(‘正在请求的url是:’,url)
#在异步协程中如果出现同步模块相关的代码,那么就无法实现异步
#time.sleep(2)
await asyncio.sleep(2)
print(‘请求成功:’,url)
#async修饰的函数,调用之后返回的一个协程对象
start = time.time()
urls = {
‘www.123.com’,
‘www.234.com’,
‘www.345.com’
}
#存放多个任务对象
stask = []
for url in urls:
c = request(url)
task = asyncio.ensure_future(c)
stask.append(task)
loop = asyncio.get_event_loop()

loop.run_until_complete(asyncio.wait(stask))

print(time.time()-start)

多任务协程异步实现
在进行多任务协程实现前,还需要建立一个简单的本地http服务

from flask import Flask
import time

app = Flask(__name__)

@app.route(‘/azb’)
def index_azb():
time.sleep(2)
return ‘Hello azb’

@app.route(‘/xx’)
def index_xx():
time.sleep(2)
return ‘Hello xx’

@app.route(‘/hh’)
def index_hh():
time.sleep(2)
return ‘Hello hh’

if __name__ == ‘__main__’:
app.run(threaded=True)

%title插图%num
实现

import requests,asyncio,time

start = time.time()
urls = [
‘http://127.0.0.1:5000/azb’,’http://127.0.0.1:5000/xx’,’http://127.0.0.1:5000/hh’
]

async def get_page(url):
print(‘正在下载’,url)
#request是基于同步,必须使用基于异步的网络请求模块
response = requests.get(url=url)
print(‘下载成功!’,url)

tasks = []

for url in urls:
c = get_page(url)
task = asyncio.ensure_future(c)
tasks.append(task)

loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.wait(tasks))

print(‘总耗时’,time.time()-start)
%title插图%num

aiohttp模块引入
import requests,asyncio,time,aiohttp

start = time.time()
urls = [
‘http://127.0.0.1:5000/azb’,’http://127.0.0.1:5000/xx’,’http://127.0.0.1:5000/hh’
]

async def get_page(url):
async with aiohttp.ClientSession() as session:
async with await session.get(url) as response:
#text()返回字符串形式的响应数据
#read()返回的二进制形式的响应数据
#json()返回的就是json对象
#获取响应数据操作之前一定要使用await进行手动挂起

page_text = await response.text()
print(page_text)

tasks = []

for url in urls:
c = get_page(url)
task = asyncio.ensure_future(c)
tasks.append(task)

loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.wait(tasks))

print(‘总耗时’,time.time()-start)%title插图%num

 

协程还是没有理解

Android Fragment 真正的完全解析(上)

自从Fragment出现,曾经有段时间,感觉大家谈什么都能跟Fragment谈上关系,做什么都要问下Fragment能实现不~~~哈哈,是不是有点过~~~

本篇博客力求为大家说明Fragment如何产生,什么是Fragment,Fragment生命周期,如何静态和动态的使用Fragment,Fragment回退栈,Fragment事务;以及Fragment的一些特殊用途,例如:没有布局的Fragment有何用处?Fragment如何与Activity交互?Fragment如何创建对话框?Fragment如何与ActionBar集成等等。

1、Fragment的产生与介绍

Android运行在各种各样的设备中,有小屏幕的手机,超大屏的平板甚至电视。针对屏幕尺寸的差距,很多情况下,都是先针对手机开发一套App,然后拷贝一份,修改布局以适应平板神马超级大屏的。难道无法做到一个App可以同时适应手机和平板么,当然了,必须有啊。Fragment的出现就是为了解决这样的问题。你可以把Fragment当成Activity的一个界面的一个组成部分,甚至Activity的界面可以完全有不同的Fragment组成,更帅气的是Fragment拥有自己的生命周期和接收、处理用户的事件,这样就不必在Activity写一堆控件的事件处理的代码了。更为重要的是,你可以动态的添加、替换和移除某个Fragment。

2、Fragment的生命周期

Fragment必须是依存与Activity而存在的,因此Activity的生命周期会直接影响到Fragment的生命周期。官网这张图很好的说明了两者生命周期的关系:

%title插图%num

可以看到Fragment比Activity多了几个额外的生命周期回调方法:
onAttach(Activity)
当Fragment与Activity发生关联时调用。
onCreateView(LayoutInflater, ViewGroup,Bundle)
创建该Fragment的视图
onActivityCreated(Bundle)
当Activity的onCreate方法返回时调用
onDestoryView()
与onCreateView想对应,当该Fragment的视图被移除时调用
onDetach()
与onAttach相对应,当Fragment与Activity关联被取消时调用
注意:除了onCreateView,其他的所有方法如果你重写了,必须调用父类对于该方法的实现,

3、静态的使用Fragment

嘿嘿,终于到使用的时刻了~~

这是使用Fragment*简单的一种方式,把Fragment当成普通的控件,直接写在Activity的布局文件中。步骤:

1、继承Fragment,重写onCreateView决定Fragemnt的布局

2、在Activity中声明此Fragment,就当和普通的View一样

下面展示一个例子(我使用2个Fragment作为Activity的布局,一个Fragment用于标题布局,一个Fragment用于内容布局):

TitleFragment的布局文件:

  1. <?xml version=”1.0″ encoding=”utf-8″?>
  2. <RelativeLayout xmlns:android=“http://schemas.android.com/apk/res/android”
  3. android:layout_width=“match_parent”
  4. android:layout_height=“45dp”
  5. android:background=“@drawable/title_bar” >
  6. <ImageButton
  7. android:id=“@+id/id_title_left_btn”
  8. android:layout_width=“wrap_content”
  9. android:layout_height=“wrap_content”
  10. android:layout_centerVertical=“true”
  11. android:layout_marginLeft=“3dp”
  12. android:background=“@drawable/showleft_selector” />
  13. <TextView
  14. android:layout_width=“fill_parent”
  15. android:layout_height=“fill_parent”
  16. android:gravity=“center”
  17. android:text=“我不是微信”
  18. android:textColor=“#fff”
  19. android:textSize=“20sp”
  20. android:textStyle=“bold” />
  21. </RelativeLayout>

TitleFragment

  1. package com.zhy.zhy_fragments;
  2. import android.app.Fragment;
  3. import android.os.Bundle;
  4. import android.view.LayoutInflater;
  5. import android.view.View;
  6. import android.view.View.OnClickListener;
  7. import android.view.ViewGroup;
  8. import android.widget.ImageButton;
  9. import android.widget.Toast;
  10. public class TitleFragment extends Fragment
  11. {
  12. private ImageButton mLeftMenu;
  13. @Override
  14. public View onCreateView(LayoutInflater inflater, ViewGroup container,
  15. Bundle savedInstanceState)
  16. {
  17. View view = inflater.inflate(R.layout.fragment_title, container, false);
  18. mLeftMenu = (ImageButton) view.findViewById(R.id.id_title_left_btn);
  19. mLeftMenu.setOnClickListener(new OnClickListener()
  20. {
  21. @Override
  22. public void onClick(View v)
  23. {
  24. Toast.makeText(getActivity(),
  25. “i am an ImageButton in TitleFragment ! “,
  26. Toast.LENGTH_SHORT).show();
  27. }
  28. });
  29. return view;
  30. }
  31. }

同理还有ContentFragment的其布局文件:

  1. <?xml version=”1.0″ encoding=”utf-8″?>
  2. <LinearLayout xmlns:android=“http://schemas.android.com/apk/res/android”
  3. android:layout_width=“match_parent”
  4. android:layout_height=“match_parent”
  5. android:orientation=“vertical” >
  6. <TextView
  7. android:layout_width=“fill_parent”
  8. android:layout_height=“fill_parent”
  9. android:gravity=“center”
  10. android:text=“使用Fragment做主面板”
  11. android:textSize=“20sp”
  12. android:textStyle=“bold” />
  13. </LinearLayout>

 

  1. package com.zhy.zhy_fragments;
  2. import android.app.Fragment;
  3. import android.os.Bundle;
  4. import android.view.LayoutInflater;
  5. import android.view.View;
  6. import android.view.ViewGroup;
  7. public class ContentFragment extends Fragment
  8. {
  9. @Override
  10. public View onCreateView(LayoutInflater inflater, ViewGroup container,
  11. Bundle savedInstanceState)
  12. {
  13. return inflater.inflate(R.layout.fragment_content, container, false);
  14. }
  15. }

MainActivity

  1. package com.zhy.zhy_fragments;
  2. import android.app.Activity;
  3. import android.os.Bundle;
  4. import android.view.Window;
  5. public class MainActivity extends Activity
  6. {
  7. @Override
  8. protected void onCreate(Bundle savedInstanceState)
  9. {
  10. super.onCreate(savedInstanceState);
  11. requestWindowFeature(Window.FEATURE_NO_TITLE);
  12. setContentView(R.layout.activity_main);
  13. }
  14. }

Activity的布局文件:

  1. <RelativeLayout xmlns:android=“http://schemas.android.com/apk/res/android”
  2. xmlns:tools=“http://schemas.android.com/tools”
  3. android:layout_width=“match_parent”
  4. android:layout_height=“match_parent” >
  5. <fragment
  6. android:id=“@+id/id_fragment_title”
  7. android:name=“com.zhy.zhy_fragments.TitleFragment”
  8. android:layout_width=“fill_parent”
  9. android:layout_height=“45dp” />
  10. <fragment
  11. android:layout_below=“@id/id_fragment_title”
  12. android:id=“@+id/id_fragment_content”
  13. android:name=“com.zhy.zhy_fragments.ContentFragment”
  14. android:layout_width=“fill_parent”
  15. android:layout_height=“fill_parent” />
  16. </RelativeLayout>

是不是把Fragment当成普通的View一样声明在Activity的布局文件中,然后所有控件的事件处理等代码都由各自的Fragment去处理,瞬间觉得Activity好干净有木有~~代码的可读性、复用性以及可维护性是不是瞬间提升了~~~下面看下效果图:

%title插图%num

4、动态的使用Fragment

上面已经演示了,*简单的使用Fragment的方式~下面介绍如何动态的添加、更新、以及删除Fragment

为了动态使用Fragment,我们修改一下Actvity的布局文件,中间使用一个FrameLayout,下面添加四个按钮~~~嘿嘿~~不是微信的按钮- -!

  1. <RelativeLayout xmlns:android=“http://schemas.android.com/apk/res/android”
  2. xmlns:tools=“http://schemas.android.com/tools”
  3. android:layout_width=“match_parent”
  4. android:layout_height=“match_parent” >
  5. <fragment
  6. android:id=“@+id/id_fragment_title”
  7. android:name=“com.zhy.zhy_fragments.TitleFragment”
  8. android:layout_width=“fill_parent”
  9. android:layout_height=“45dp” />
  10. <include
  11. android:id=“@+id/id_ly_bottombar”
  12. android:layout_width=“fill_parent”
  13. android:layout_height=“55dp”
  14. android:layout_alignParentBottom=“true”
  15. layout=“@layout/bottombar” />
  16. <FrameLayout
  17. android:id=“@+id/id_content”
  18. android:layout_width=“fill_parent”
  19. android:layout_height=“fill_parent”
  20. android:layout_above=“@id/id_ly_bottombar”
  21. android:layout_below=“@id/id_fragment_title” />
  22. </RelativeLayout>

底部四个按钮的布局就不贴了,到时看效果图就明白了~~

下面主Activity

  1. package com.zhy.zhy_fragments;
  2. import android.app.Activity;
  3. import android.app.FragmentManager;
  4. import android.app.FragmentTransaction;
  5. import android.os.Bundle;
  6. import android.view.View;
  7. import android.view.View.OnClickListener;
  8. import android.view.Window;
  9. import android.widget.LinearLayout;
  10. public class MainActivity extends Activity implements OnClickListener
  11. {
  12. private LinearLayout mTabWeixin;
  13. private LinearLayout mTabFriend;
  14. private ContentFragment mWeixin;
  15. private FriendFragment mFriend;
  16. @Override
  17. protected void onCreate(Bundle savedInstanceState)
  18. {
  19. super.onCreate(savedInstanceState);
  20. requestWindowFeature(Window.FEATURE_NO_TITLE);
  21. setContentView(R.layout.activity_main);
  22. // 初始化控件和声明事件
  23. mTabWeixin = (LinearLayout) findViewById(R.id.tab_bottom_weixin);
  24. mTabFriend = (LinearLayout) findViewById(R.id.tab_bottom_friend);
  25. mTabWeixin.setOnClickListener(this);
  26. mTabFriend.setOnClickListener(this);
  27. // 设置默认的Fragment
  28. setDefaultFragment();
  29. }
  30. private void setDefaultFragment()
  31. {
  32. FragmentManager fm = getFragmentManager();
  33. FragmentTransaction transaction = fm.beginTransaction();
  34. mWeixin = new ContentFragment();
  35. transaction.replace(R.id.id_content, mWeixin);
  36. transaction.commit();
  37. }
  38. @Override
  39. public void onClick(View v)
  40. {
  41. FragmentManager fm = getFragmentManager();
  42. // 开启Fragment事务
  43. FragmentTransaction transaction = fm.beginTransaction();
  44. switch (v.getId())
  45. {
  46. case R.id.tab_bottom_weixin:
  47. if (mWeixin == null)
  48. {
  49. mWeixin = new ContentFragment();
  50. }
  51. // 使用当前Fragment的布局替代id_content的控件
  52. transaction.replace(R.id.id_content, mWeixin);
  53. break;
  54. case R.id.tab_bottom_friend:
  55. if (mFriend == null)
  56. {
  57. mFriend = new FriendFragment();
  58. }
  59. transaction.replace(R.id.id_content, mFriend);
  60. break;
  61. }
  62. // transaction.addToBackStack();
  63. // 事务提交
  64. transaction.commit();
  65. }
  66. }

可以看到我们使用FragmentManager对Fragment进行了动态的加载,这里使用的是replace方法~~下一节我会详细介绍FragmentManager的常用API。

注:如果使用Android3.0以下的版本,需要引入v4的包,然后Activity继承FragmentActivity,然后通过getSupportFragmentManager获得FragmentManager。不过还是建议版Menifest文件的uses-sdk的minSdkVersion和targetSdkVersion都改为11以上,这样就不必引入v4包了。

代码中间还有两个Fragment的子类,ContentFragment上面已经见过,FriendFragment其实类似:

  1. package com.zhy.zhy_fragments;
  2. import android.app.Fragment;
  3. import android.os.Bundle;
  4. import android.view.LayoutInflater;
  5. import android.view.View;
  6. import android.view.ViewGroup;
  7. public class FriendFragment extends Fragment
  8. {
  9. @Override
  10. public View onCreateView(LayoutInflater inflater, ViewGroup container,
  11. Bundle savedInstanceState)
  12. {
  13. return inflater.inflate(R.layout.fragment_friend, container, false);
  14. }
  15. }

效果图:

%title插图%num

可以看到很好的实现了效果,有兴趣可以看看。

5、Fragment家族常用的API

Fragment常用的三个类:

android.app.Fragment 主要用于定义Fragment

android.app.FragmentManager 主要用于在Activity中操作Fragment

android.app.FragmentTransaction 保证一些列Fragment操作的原子性,熟悉事务这个词,一定能明白~

a、获取FragmentManage的方式:

getFragmentManager() // v4中,getSupportFragmentManager

b、主要的操作都是FragmentTransaction的方法

FragmentTransaction transaction = fm.benginTransatcion();//开启一个事务

transaction.add() 

往Activity中添加一个Fragment

transaction.remove()

从Activity中移除一个Fragment,如果被移除的Fragment没有添加到回退栈(回退栈后面会详细说),这个Fragment实例将会被销毁。

transaction.replace()

使用另一个Fragment替换当前的,实际上就是remove()然后add()的合体~

transaction.hide()

隐藏当前的Fragment,仅仅是设为不可见,并不会销毁

transaction.show()

显示之前隐藏的Fragment

detach()

会将view从UI中移除,和remove()不同,此时fragment的状态依然由FragmentManager维护。

attach()

重建view视图,附加到UI上并显示。

transatcion.commit()//提交一个事务

注意:常用Fragment的哥们,可能会经常遇到这样Activity状态不一致:State loss这样的错误。主要是因为:commit方法一定要在Activity.onSaveInstance()之前调用。

上述,基本是操作Fragment的所有的方式了,在一个事务开启到提交可以进行多个的添加、移除、替换等操作。

值得注意的是:如果你喜欢使用Fragment,一定要清楚这些方法,哪个会销毁视图,哪个会销毁实例,哪个仅仅只是隐藏,这样才能更好的使用它们。

a、比如:我在FragmentA中的EditText填了一些数据,当切换到FragmentB时,如果希望会到A还能看到数据,则适合你的就是hide和show;也就是说,希望保留用户操作的面板,你可以使用hide和show,当然了不要使劲在那new实例,进行下非null判断。

b、再比如:我不希望保留用户操作,你可以使用remove(),然后add();或者使用replace()这个和remove,add是相同的效果。

c、remove和detach有一点细微的区别,在不考虑回退栈的情况下,remove会销毁整个Fragment实例,而detach则只是销毁其视图结构,实例并不会被销毁。那么二者怎么取舍使用呢?如果你的当前Activity一直存在,那么在不希望保留用户操作的时候,你可以优先使用detach。

上述已经介绍完成了Fragment常用的一些方法,相信看完,大家一定清楚了Fragment的产生理由,以及如何使用Fragment,再根据API的讲解,也能明白,曾经为何觉得Fragment会出现一些列乱七八槽的问题,终究是因为没有弄清楚其生命周期。

由于篇幅原因,剩下的内容留到下一篇了。在下一篇,会介绍:

1、如何管理Fragment回退栈

2、Fragment如何与Activity交互

3、Fragment与Activity交互的*佳实践

4、没有视图的Fragment的用处

5、使用Fragment创建对话框

6、如何与ActionBar,MenuItem集成等~~

 

会将view从UI中移除,和remove()不同,此时fragment的状态依然由FragmentManager维护。

Ivanti Neurons™神经元:远程边缘设备实现自主、自动、自助管理

打造可愈合的自主边缘(Autonomous Edge),让远程工作人员提前结合上下文,实现远程边缘设备的自助管理。

近日,致力于通过统一IT为企业用户提供更加高效安全数字化工作场所的Ivanti发布了基于深度学习技术的超级自动化平台——Ivanti Neurons™ 神经元。

该平台赋予企业自主愈合和保护边缘设备的能力,并重新诠释了为*终用户提供IT自助服务的理念。

通过一系列智能应用,*终用户可自主进行检测和修复边缘设备,企业IT团队的服务效率将获得大幅提升,管理成本显著减少。

目前,已采用Ivanti Neurons™ 神经元的企业可将意外停运时间减少63%,部署安全升级的时间缩短88%,并在用户上报之前解决多达80%的端点设备问题。

%title插图%num

Ivanti Neurons™神经元的全新上线,标志着Ivanti进一步实现其预见性和前瞻性,即打造超级自动化平台,帮助企业用户有效地应对日益繁复的设备、数据和远程工作人员的管理问题,以及层出不穷的安全威胁,助力企业IT管理从基础的自动化转型,走向成熟的超级自动化,为远程工作人员提供可愈合的自主体验,帮助其提前结合自身状况,实现远程边缘设备的自助管理。

Ivanti执行副总裁兼首席产品总监Nayaki Nayyar表示:“随着远程工作模式成为下一个常态,Ivanti Neurons™ 神经元不仅为企业提供了自主修复和保护端点设备的能力,还为员工提供了 ‘随时随地工作’的无缝体验。借助可自主检修和保护边缘端点设备的智能应用,IT部门将实现‘及早发现,及时解决问题’的工作目标。”

金斯顿大学技术服务负责人Daniel Bolton表示:“Ivanti Neurons™神经元提供主动式监测,让我们随时掌握各设备电池的使用情况及寿命,节省了大量资产采购和维修成本。而且,Ivanti Neurons™神经元能在短时间内为技术部门提供动态信息,帮助我们做出更合理的决策,确保在校员工和学生高效地完成工作及学习。”

Ivanti Neurons™超级自动化平台,可为企业及组织提供多项功能,包括:

· Ivanti Neurons™ for Edge Intelligence边缘设备智能化: 这项基于自然语言处理技术(NLP)的功能,将帮助IT团队快速查询所有边缘设备,在短时间内获取内部整体信息;它还拥有基于传感器的架构,可以帮助企业迅速了解边缘设备的运营环境,实时清点资产,并做好安全配置。

· Ivanti Neurons™ for Healing自我治疗:该功能可提供一系列智能应用,可主动检测、诊断和自动修复端点设备的配置问题、合规问题及安全问题,实现常规任务自动化,为打造真正的IT自愈合环境铺平道路,大大提升效率并缩减成本,改善用户体验。

· Ivanti Neurons™ for Discovery发现:该功能可在短时间内提供准确而实用的资产信息,通过主动扫描、被动扫描和第三方连接器,提供实时的可视化功能。这些规范化的软硬件资产清点数据、软件使用信息以及实用的洞察,有助于高效地配置管理数据库和资产管理数据库。

· Ivanti Neurons™ Workspace工作空间:该功能基于实时数据,提供了从设备、用户,到应用程序和服务的360度全方位视图,可帮助一线IT人员解决原本需要向专家上报的问题,消除问题上报带来的复杂性,同时缩短等待时间并降低上报成本,有助于加快解决*终用户的问题,大幅提高工作效率。

如今云服务器大行其道的时代,如何选购物理服务器?

用途:公司内部系统使用

网上找了一圈,也没发现啥有价值的选购指南,不知道该看哪些参数等等。
特来问问各位大佬们!

locoz 2020-01-11 01:50:41 +08:00 via Android
具体需求呢…内部系统消耗哪方面资源比较多总得搞清楚吧?要哪方面性能高也得搞清楚吧?搞清楚了之后无非就是对症下药堆配置了。
CPU 现在的话可以试试 AMD…香到爆炸…
mashaofeixxx 2
mashaofeixxx 2020-01-11 08:39:50 +08:00
对配置要求高吗 nuc 能满足吗?
s609926202 3
s609926202 2020-01-11 08:40:45 +08:00 via iPhone
@locoz @mashaofeixxx
就是 erp 系统
mashaofeixxx 4
mashaofeixxx 2020-01-11 08:43:33 +08:00
@s609926202 我前两天给客户使用 nuc 部署了 用友 要不咱俩聊聊 我做 nuc 服务器这块 提供公网解决方案
我的 wx: d2cc67aa8cD66D1b 不需要解密,直接加,加个好友聊聊.
ladypxy 5
ladypxy 2020-01-11 09:02:14 +08:00 via iPhone
这种问题有啥问的意义么
物理服务器就那几家,ibm HP dell,直接买就好了
s609926202 6
s609926202 2020-01-11 09:29:51 +08:00 via iPhone
@ladypxy 货比三家,买*合适的
murmur 7
murmur 2020-01-11 10:04:10 +08:00
机房用就选服务好的,一个电话就能叫上门的,不过原厂服务贵到坑 b 就是了,自用就学翼王这种自己组配件
反正 2u 的机箱基本上 ATX 组件可以随便用,不存在组装问题,而且因为体积大所以风扇也比较柔和
stoneabc 8
stoneabc 2020-01-11 11:30:36 +08:00
小公司没严格要求的话,可以找找各大云厂商 3 年淘汰的旧机器。。
venster 9
venster 2020-01-11 11:37:23 +08:00 via Android
记住:别买联想,下个驱动还得到美国站去下载,中国站找一天都不一定找得到。其他的戴尔惠普直接联系网站销售就行了。
abbottcn 10
abbottcn 2020-01-11 12:15:04 +08:00 via iPhone
可能和大家的用途差太多。做 CPU 密集型计算,组装的服务器。放机房的。服务器主板,有个毛病,启动贼慢。根据需求,配置非常灵活,比浪潮的整机便宜特别多。

NerverLibis 2020-01-11 12:32:20 +08:00 via iPhone
@venster 就算是笔记本也不能碰联想,除非有回扣
herozzm 12
herozzm 2020-01-11 12:39:57 +08:00
@ladypxy +1
328730311 13
328730311 2020-01-11 13:51:04 +08:00
dell r740 2u 8 核*2/16g*4/1.2t 10k 2.5 寸 *4 ( raid5 )/idrac 远控 /单电源,(或者塔式服务 dell t640 )参考这个配置。如果预算有限,可以用刚停产的 r730 或者 t630。
MeteorCat 14
MeteorCat 2020-01-11 13:54:40 +08:00 via Android
我买了专线宽带+gen8+gen10 自己搭服务器,实际上*开始用阿里云服务器现在 1G2M 带宽续费一年 1500 一计算还不如自己去接入专线买个高配置主机
594duck 15
594duck 2020-01-12 15:36:42 +08:00 via iPhone
10 年运维在这里
s609926202 16
s609926202 2020-01-12 16:42:11 +08:00 via iPhone
@594duck 请问本地物理服务器除了专线固定 ip 还有其他办法实现公网访问吗?
594duck 17
594duck 2020-01-12 20:34:33 +08:00 via iPhone
@s609926202

你是指公网访问你的服务器,可以用的电脑上,(动态的 dns )防火墙都带一些的,映射下就好。但是在今天的国内线路里边很痛苦。运营商会封锁

ntp crontab同步集群服务器时间

实际情形:当服务器非常多的时候,比如1000台服务器,要求每天或者某个时间点开启服务,或者执行一项job。

配置过程

首先检查 ntp 命令是否安装

没有安装则安装一下 yum install ntp ntpdate -y

为了方便切换到root用户执行

su root

编辑配置文件

vim /etc/ntp.conf

如图

%title插图%num

在文件末尾添加

server 127.127.1.0

fudge 127.127.1.0 stratum 10

解释:

1、去掉注释,是允许192.168.1.0 网段的服务器来获取时间

2、添加注释,禁用使用其他网段服务器的时间

3、当该节点丢失网络连接,依然可以采用本地时间作为时间服务器为集群中的其他节点提供时间同步

vim /etc/sysconfig/ntpd

添加以后代码

SYNC_HWCLOCK=yes

启动ntp服务器
首先查看ntp服务器的状态

service ntpd status

如图

%title插图%num

启动ntp服务器

service ntpd start

%title插图%num

设置开机自启:chkconfig ntpd on

*后检测是否配置成功了
登录到其他服务器上(在一个网段内的)

上面我是将hadoop112作为ntp服务器

下面我进入hadoop113服务器 (root身份)

输入crontab -e

添加代码

*/1 * * * * /usr/sbin/ntpdate hadoop112

意思是每隔1分钟同步一次时间

%title插图%num

退出编辑后按照下面的查看时间,修改时间。然后等待一分钟查看一下时间有没有自动修改回来

%title插图%num

扩展知识:

crontab讲解

在上方出现了crontab -e

并且添加了一行代码,下面进行讲解

*/1 * * * * /usr/sbin/ntpdate hadoop112

基本格式 :
*      *   *    *   *  command
分 时 日 月 周   命令

iOS14,删个 APP 需要点三次,苹果公司是怎么想的?

才发现在资源库里,长按图标,弹出的菜单里选择删除,iOS14 就问一次,点确定就删除了。

45 条回复    2021-03-27 10:33:47 +08:00
mh
    1

mh   22 小时 36 分钟前

不是两次么
whileFalse
    2

whileFalse   22 小时 35 分钟前   ❤️ 1

你删除 APP 的频率有多高?
hash
    3

hash   22 小时 34 分钟前   ❤️ 1

*后一次确认确实意义非常有限
hlobo
    4

hlobo   22 小时 33 分钟前 via Android   ❤️ 30

少用那些,装上用 15 分钟就删掉的 app,注意身体
stark123
    5

stark123   22 小时 30 分钟前

@whileFalse 我才转到 iOS 上。下载了很多 APP 试验,不好的就都删掉。今天删了 40 多个了。
xnotepad
    6

xnotepad   22 小时 29 分钟前

装个 APP 还得按两次关闭按钮呢。这样一比,是不是觉得你那个三次点击也就没啥了。
superrichman
    7

superrichman   22 小时 26 分钟前 via iPhone

你就当多点一下是帮你清空数据好了,ios 不会跟安卓一样删了 app 还留一堆乱七八糟的文件夹
MidAutumnMoon
    8

MidAutumnMoon   22 小时 23 分钟前 via iPhone

确实现在的操作不如以前那样自然,这方面 iOS 就像走了倒车似的( imo )
finab
    9

finab   22 小时 20 分钟前   ❤️ 1

嘿嘿,我可以压缩到俩次~
按住 弹出菜单后手指滑到删除按钮再松开,再点确认~
deplives
    10

deplives   22 小时 19 分钟前 via iPhone   ❤️ 3

两次吧你就要问 为啥删除前不确认一次,万一误删除咋办,三次吧又问为啥还要点三次,
现在就差直接读取你脑子里的想法了,这样一次也不用点

 

dingdangnao
    11

dingdangnao   22 小时 19 分钟前

真心觉得 iOS 的某些交互需要改改了。。。比如左上角返回。。MAX 一只手根本点不到左上角。。
(尤其国内某些垃圾 app 没有左滑返回,只能点左上角

iOS 的主界面的图标,iPhone 12 Pro Max 只比 iPhone 5 多了一排。。。傻大笨的感觉。。哎

whileFalse
    12

whileFalse   22 小时 8 分钟前

@stark123 特别想知道你是怎么样点 3 次才删除的。我都是两次。
Astrian
    13

Astrian   22 小时 2 分钟前

我猜你是通过按住图标会出现 context menu 里面的删除按钮来删除 app……
弹出 context menu 继续按住就会变成经典的抖图标
flineqaq
    14

flineqaq   22 小时 0 分钟前 via iPhone

3 次很多么……你把发这个帖子的点击次数省下来,按 2 次的指标够用十几年了╮( ̄▽ ̄””)╭
so898
    15

so898   21 小时 47 分钟前

@dingdangnao 把 Home Indicator (底部的那个横条)往下拨动一下会有惊喜
JoJoJoJ
    16

JoJoJoJ   21 小时 46 分钟前 via iPhone

google 的 hangout,删除一条短信要按 6 次
kop1989
    17

kop1989   21 小时 41 分钟前

主要是多了一个资源库( app 抽屉)。所以要确认你是要删除 app,还是删除桌面图标。
icyalala
    18

icyalala   21 小时 31 分钟前

@mh @finab @whileFalse
两次是怎么做到的?

*种方法:
1. 按住图标出现菜单,滑动到 “移除 App”
2. 在弹出的菜单中点击 “删除 App”
3. 在弹出的菜单中点击 “删除”

第二种方法:
1. 长按图标出现抖动
2. 点左上角的减号
3. 在弹出的菜单中点击 “删除 App”
4. 在弹出的菜单中点击 “删除”

感觉这套东西都是在出现了 App 资源库之后弄得一坨补丁

safarigu
    19

safarigu   21 小时 28 分钟前

感觉现在苹果 iOS 产品做得真的挺差的,该换人换人吧?
更别提 Apple TV app 要多蹩脚有多蹩脚
stark123
    20

stark123   21 小时 25 分钟前

@JoJoJoJ 6 次,这是什么天才逻辑
minami
    21

minami   21 小时 19 分钟前   ❤️ 1

苹果公司怎么想不重要,重要的是果粉怎么想。既然果粉都不觉得是个问题,那么就不是个问题。你看是不是有种哲理在里面
wovfeng
    22

wovfeng   20 小时 32 分钟前 via iPhone   ❤️ 1

说一个小众的删除方法,还可以在 app store 更新那边左滑删除。有时候发现 app 更新了,但好像有没怎么用就顺手删掉了…
petercui
    23

petercui   20 小时 2 分钟前   ❤️ 1

@xnotepad 两次握手,三次挥手。
JHExp
    24

JHExp   19 小时 56 分钟前

开关推送不能快捷操作感觉是*困扰的
wclebb
    25

wclebb   19 小时 40 分钟前 via iPhone

长按—移除,就两次啊?
From313
    26

From313   19 小时 29 分钟前

资源库搜索列表的 App 不能直接删,我是拖拽到桌面删….
ntcydia
    27

ntcydia   19 小时 27 分钟前

在两次删除 app 这个操作上 3D touch 确实是个好功能。
dingdangnao
    28

dingdangnao   19 小时 17 分钟前

@so898 是 确实有所谓的“便捷访问”什么的,你可以去试试看 max 机型, 拇指能不能够得到屏幕一半*左边?
zbatman
    29

zbatman   17 小时 15 分钟前 via Android

是你不会用吧,苹果的设计师不比你懂手机?[狗头]
kiripeng
    30

kiripeng   17 小时 12 分钟前

苹果就是把用户当孙子,而*新的苹果手机对用户的政策是当傻子。( mac 在手我还是这么说)
minamike
    31

minamike   17 小时 0 分钟前 via iPhone

@From313 可以删的 列表里长按图标出现菜单就能删除了
appstore54321
    32

appstore54321   16 小时 44 分钟前 via iPhone

还不是你不会用.jpg

果粉怎么回事?

youcandoit
    33

youcandoit   16 小时 36 分钟前 via iPhone

@hlobo #4 这是什么梗啊……
drawstar
    34

drawstar   16 小时 4 分钟前 via iPhone

@whileFalse 每次进入贤者时间 doge
felixcode
    35

felixcode   15 小时 55 分钟前   ❤️ 1

*近学到了一个超好用的句型:

你们扪心自问一下,你真的需要只点两次就删除 APP 吗?

stark123
    36

stark123   15 小时 46 分钟前

@felixcode 不试用怎么知道是否合适。不合适难道留着过年?
hkezh
    37

hkezh   15 小时 25 分钟前 via iPhone   ❤️ 1

应该给一个资源库开关,不是所有人都喜欢
stark123
    38

stark123   15 小时 17 分钟前

@hkezh 那玩意我非常讨厌。根本用不上。
SenLief
    39

SenLief   15 小时 11 分钟前

苹果的用意是让用户形成习惯,习惯就好了,毕竟我觉得我是对的。
orangy
    40

orangy   14 小时 22 分钟前 via iPhone

@JHExp 长按消息,右上角会出现三点,点击三点,就可以管理该条消息 app 的推送设置了,你是指这个快捷操作吗??
5966
    41

5966   12 小时 33 分钟前 via iPhone

当你在 Safari 打开很多标签,想全部关闭,1,Safari 长按右下角图标,弹出,2,关闭 n 个标签页,还没有完,3,确认关闭吗?
stark123
    42

stark123   11 小时 52 分钟前

@5966 哈哈哈,这逻辑,够 2 的。
daerzei
    43

daerzei   11 小时 23 分钟前 via iPhone

我收集限免应用(下完就删)时体会到了,那个资源库确实没卵用还憨憨,以前确认一下就删了,现在点错了还得去资源库找
littlewing
    44

littlewing   11 小时 19 分钟前

@daerzei 不用真的下载吧,直接点一下,然后取消下载
rcw
    45

rcw   18 分钟前 via iPhone

可能苹果觉得你不会经常删 app

iOS开发-GCD技术

文章目录
前言
Dispatch Queue
Queue Create
Queue Release
MRC
ARC
Global Queue
如何设置QOS级别
Dispatch Set Target
dispatch_after
GCD timer
Dispatch Group
dispatch_group_notify
dispatch_group_wait
dispatch_barrier_async
dispatch_apply
dispatch_resume/dispatch_suspend
dispatch TLS
前言
对于OS X和iOS的XNU内核线程切换时,会进行上下文切换,例如CPU的寄存器等信息保存到各自路径专用的内存块中,从切换目标路径专用的内存块中,复原CPU寄存器等信息,继续执行切换路径的CPU命令行。这被称为“上下文切换”。

使用多线程的程序可以在某个线程和其他线程之间反复多次进行上下文切换,因此看上去就好像1个CPU核能够并列的执行多个线程一样。而且在具有多个CPU核的情况下,就不是“看上去像”了,而是真的提供了多个CPU核并行执行多个线程的技术。

多线程编程易发生各种问题,例如多个线程对资源的竞争,多个线程之间相互等待造成死锁,以及线程开辟消耗大量的内存等问题。

%title插图%num

多线程的优点在于能够将复杂的处理独立出来,不会阻塞主线程这种线程的执行

%title插图%num

GCD是基于XNU内核的线程技术,大大简化了多线程编程的源码。

Dispatch Queue
一般来说我们会这样异步执行一个任务

1   dispatch_async(queue,^{
2  //do your task
3  });

queue代表一个队列,在GCD中存在两种队列形式

Serial Dispatch Queue 串行队列
Concurrent Dispatch Queue 并行队列
两种队列的在于,Serial处理task是根据队列先进先出顺序执行,会保证上一个task执行完再执行下一个,而Concurrent则是并发执行,不会等上一个task执行完

%title插图%num

虽然Concurrent Dispatch Queue不用等待处理结束,可以并发执行多个task,但是其并发线程的数量却是取决于当前系统的状态。根据如下:

iOS和OS X基于Dispatch Queue中的处理数
CPU核数以及CPU负荷等当前系统的状态
来决定Concurrent Dispatch Queue中线程数量。

例如:

1    dispatch_asyc(queue,blk0)
2   //.. 1 ~ 6
3   dispatch_asyc(queue,blk7)

8个task可能根据当前系统的状态,会如下执行:

%title插图%num

Queue Create
我们可以通过GCD的API来生成Dispatch Queue

dispatch_queue_t mySerialDispatchQueue = dispatch_queue_create(“com.example.gcd.MySerialDispatchQueue”,DISPATCH_QUEUE_SERIAL)

值得注意的是Serial Dispatch Queue的生成,当创建一个Serial Dispatch Queue,系统就默认只生成并使用一个线程。如果生成了2000个Serial Dispatch Queue那么就创建2000个线程,这对内存资源消耗是很大的。而Concurrent Dispatch Queue就没这个问题,他会根据系统状态来管理并发线程数量,所以虽然我们可以使用创建多个Serial Dispatch Queue来达到并发的目的,但是并不是GCD的初衷,我们应该使用Concurrent Dispatch Queue来处理并发任务

同样我们可以创建 Concurrent Dispatch Queue

dispatch_queue_t myConcurrentDispatchQueue = dispatch_queue_create(“com.example.gcd.MyConcurrentDispatchQueue”,DISPATCH_QUEUE_CONCURRENT)

即第二个参数决定了Queue的类型是 Serial 还是 Concurrent

Queue Release
MRC
对于Dispatch Queue,Queue必须创建后由程序员自己释放,因为Dispatch Queue并没有像block那样具有作为Object-C对象来处理的技术。

dispatch_release(myConcurrentDispatchQueue)

但是,Dispatch Queue同样有引用计数管理。意味着你可以

dispatch_retain(myConcurrentDispatchQueue)

例如下面代码

dispatch_queue_t myConcurrentDispatchQueue = dispatch_queue_create(“com.example.gcd.MyConcurrentDispatchQueue”,DISPATCH_QUEUE_CONCURRENT);
dispatch_async(myConcurrentDispatchQueue, ^{
//do your task
});
dispatch_release(myConcurrentDispatchQueue);

既然dispatch_release释放掉了,为什么任务还能执行,这也是因为block对queue进行了引用,就相当于调用了dispatch_retain

ARC
对于ARC模式下,你不需要手动调用dispatch_release(myConcurrentDispatchQueue);,ARC已经允许将Dispatch Queue作为对象加入ARC内存管理。

Global Queue
我们可以获取系统为我们提供的标准Global Queue,

在iOS 7之前,系统提供了4种优先级,以调度优先级区分

名称 执行优先级
DISPATCH_QUEUE_PRIORITY_HIGH 高(*高优先)
DISPATCH_QUEUE_PRIORITY_DEFAULT 默认
DISPATCH_QUEUE_PRIORITY_LOW 低
DISPATCH_QUEUE_PRIORITY_BACKGROUND 后台
在iOS 8之后,系统提供了5种优先级,以服务质量划分的

名称 执行优先级
QOS_CLASS_USER_INTERATCTIVE 高(*高优先)
QOS_CLASS_USER_INITIATED 用户交互(不要使用耗时操作)
QOS_CLASS_DEFAULT 默认
QOS_CLASS_UTILITY 使用工具(用了做耗时操作)
QOS_CLASS_BACKGROUND 后台执行
QOS_CLASS_UNSPECIFIED 没有指定优先级
对于QOS_CLASS_UTILITY我们一般进行耗时操作,例如数据I/O,系统对其进行了优化,使得能够减少App的电量消耗。

如何设置QOS级别
dipatch_queue_attr_make_with_qos_class 或dispatch_set_target_queue方法设置队列的优先级

1 //dipatch_queue_attr_make_with_qos_class
2
3 dispatch_queue_attr_t attr = dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_SERIAL, QOS_CLASS_UTILITY, -1);
4
5 dispatch_queue_t queue = dispatch_queue_create(“com.starming.gcddemo.qosqueue”, attr);
6
7
8
9 //dispatch_set_target_queue
10
11 dispatch_queue_t queue = dispatch_queue_create(“com.starming.gcddemo.settargetqueue”,NULL); //需要设置优先级的queue
12
13 dispatch_queue_t referQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0); //参考优先级
14
15 dispatch_set_target_queue(queue, referQueue); //设置queue和referQueue的优先级一样

Dispatch Set Target
void dispatch_set_target_queue(dispatch_object_t object, dispatch_queue_t _Nullable queue);

dispatch_set_target_queue能够设置queue的执行阶层,无论是Concurrent Queue还是Serial Queue,一旦设置target为Serial Queue就是串行执行。

例如下列代码:

1 – (void)set_tag_test {
2     dispatch_queue_t serialQueue1 = dispatch_queue_create(“com.gcd.setTargetQueue2.serialQueue1”, DISPATCH_QUEUE_CONCURRENT);
3     dispatch_queue_t serialQueue2 = dispatch_queue_create(“com.gcd.setTargetQueue2.serialQueue2”, DISPATCH_QUEUE_CONCURRENT);
4     dispatch_queue_t serialQueue3 = dispatch_queue_create(“com.gcd.setTargetQueue2.serialQueue3”, DISPATCH_QUEUE_CONCURRENT);
5     dispatch_queue_t serialQueue4 = dispatch_queue_create(“com.gcd.setTargetQueue2.serialQueue4”, DISPATCH_QUEUE_CONCURRENT);
6     dispatch_queue_t serialQueue5 = dispatch_queue_create(“com.gcd.setTargetQueue2.serialQueue5”, DISPATCH_QUEUE_CONCURRENT);
7
8
9
10     //创建目标串行队列
11     dispatch_queue_t targetSerialQueue = dispatch_queue_create(“com.gcd.setTargetQueue2.targetSerialQueue”, NULL);
12
13     //设置执行阶层
14     dispatch_set_target_queue(serialQueue1, targetSerialQueue);
15     dispatch_set_target_queue(serialQueue2, targetSerialQueue);
16     dispatch_set_target_queue(serialQueue3, targetSerialQueue);
17     dispatch_set_target_queue(serialQueue4, targetSerialQueue);
18     dispatch_set_target_queue(serialQueue5, targetSerialQueue);
19
20     dispatch_async(serialQueue1, ^{
21         NSLog(@”%@,1″,[NSThread currentThread]);
22     });
23     dispatch_async(serialQueue1, ^{
24         NSLog(@”%@,1 2″,[NSThread currentThread]);
25     });
26     dispatch_async(serialQueue2, ^{
27         NSLog(@”%@,2″,[NSThread currentThread]);
28     });
29     dispatch_async(serialQueue3, ^{
30         NSLog(@”%@,3″,[NSThread currentThread]);
31     });
32     dispatch_async(serialQueue4, ^{
33         NSLog(@”%@,4″,[NSThread currentThread]);
34     });
35     dispatch_async(serialQueue5, ^{
36         NSLog(@”%@,5″,[NSThread currentThread]);
37     });
38     dispatch_async(targetSerialQueue, ^{
39         NSLog(@”%@,6″,[NSThread currentThread]);
40     });
41 }

输出为:

1 <NSThread: 0x60000239b580>{number = 3, name = (null)},1
2 <NSThread: 0x60000239b580>{number = 3, name = (null)},1 2
3 <NSThread: 0x60000239b580>{number = 3, name = (null)},2
4 <NSThread: 0x60000239b580>{number = 3, name = (null)},3
5 <NSThread: 0x60000239b580>{number = 3, name = (null)},4
6 <NSThread: 0x60000239b580>{number = 3, name = (null)},5
7 <NSThread: 0x60000239b580>{number = 3, name = (null)},6

dispatch_after
延迟执行

1     dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, 3ull * NSEC_PER_SEC);
2     dispatch_after(time, dispatch_get_main_queue(),^{
3         //do task
4     });

dispatch_after是延迟3s加入Dispatch Queue,并不是马上执行,例如加入到主线程时,如果主线程卡段,这个延迟会大于3s

某一*对时间执行
如果dispatch_after需要在2020/04/27 11:11:11执行,那么dispatch_time_t就可以使用dispatch_walltime构造

 

1   dispatch_time_t dispatch_walltime(const struct timespec *_Nullable when, int64_t delta);

1     NSTimeInterval interval = [[NSDate date] timeIntervalSince1970];
2     struct timespec time;
3     dispatch_time_t milestone;
4     double second,subsecond;
5     subsecond = modf(interval, &second);
6     time.tv_sec = second;
7     time.tv_nsec = subsecond * NSEC_PER_SEC;
8     milestone = dispatch_walltime(&time, 0);

GCD timer
1  void
2  dispatch_source_set_timer(dispatch_source_t source, //source timer
3  dispatch_time_t start, //开始时间
4  uint64_t interval, //执行间隔
5  uint64_t leeway); //允许的延迟时间 – 系统会尽量满足,但不一定保证在延迟时间内执行

一般来说我们定时器这样写:

1     timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_main_queue());
2     dispatch_source_set_timer(timer, dispatch_time(DISPATCH_TIME_NOW, (80 * NSEC_PER_MSEC)), (80 * NSEC_PER_MSEC), 0);
3     dispatch_source_set_event_handler(timer, ^{
4         //
5     });
6     dispatch_resume(timer);

注意dispatch_source是遵循ARC的,要强引用保证其不被释放。

为什么GCD定时器相比NSTimer定时器更准?
NSTimer是CFRunLoopTimerRef的toll-free bridged的,可以直接转换,当某一次执行被延后,错过了时间点,那么NSTimer会选择不执行此次回调,等到下次执行。所以相比来说,GCD定时器更为准确。

此外 GCD定时器无法保证每次的执行同时在一个线程中,就算是Serial队列也不行,而NSTimer是加入到线程的runloop中,所以必定是同一个线程,当我们需要单线程执行时,需要注意这点。

Dispatch Group
dispatch_group_notify
我们一般用dispatch_group处理多个任务完成后,执行某个操作

1 – (void)dispatch_group_test {
2     dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
3     dispatch_group_t group = dispatch_group_create();
4     dispatch_group_async(group, queue, ^{
5         NSLog(@”blk0;”);
6     });
7     dispatch_group_async(group, queue, ^{
8         NSLog(@”blk1;”);
9     });
10     dispatch_group_async(group, queue, ^{
11         NSLog(@”blk2;”);
12     });
13
14     //1. notify
15     dispatch_group_notify(group, dispatch_get_main_queue(), ^{
16         NSLog(@”done”);
17     });
18
19     //MRC
20 //    dispatch_release(group);
21 }

控制台输出为:

1 2020-04-29 16:30:20.748658+0800 GCDTest[51629:2202347] blk0;
2 2020-04-29 16:30:20.748668+0800 GCDTest[51629:2202345] blk1;
3 2020-04-29 16:30:20.748687+0800 GCDTest[51629:2202346] blk2;
4 2020-04-29 16:30:20.761685+0800 GCDTest[51629:2201079] done

追加到Dispatch Group的block会对Dispatch Group进行dispatch_retain并持有,在block 执行完之后释放Dispatch Group,所以一旦Dispatch Group使用结束,意味着block都不保持其引用了,可以放心释放。

dispatch_group_wait
判断指定时间后,task是否执行完,使用dispatch_group_wait

将上面1部分替换为:

1
2     dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, 1ull*NSEC_PER_SEC);
3     long result = dispatch_group_wait(group, time);
4
5     if (result == 0) {
6         // Group 中task全部执行完
7     }else {
8         // Group 中task还在执行中
9     }

我们可以通过将time参数设置为DISPATCH_TIME_NOW,然后在Runloop每次循环中来判断task是否执行完,以达到和dispatch_group_notify同样的效果。

我们可以通过将time参数设置为DISPATCH_TIME_FOREVER来保证任务一定执行完成。等同于dispatch_group_notify

dispatch_barrier_async
对于访问数据库文件,我们要避免数据竞争,资源是互斥的。虽然我们可以使用Serial Dispatch Queue来解决这样的问题,但是为了高效处理,写入操作确实不可与其他写入以及读取操作同时进行,但是多个读取操作时可以同时进行的,只需要保证写入是在多个读取之后进行。

1 – (void)dispatch_barrier_test {
2     dispatch_queue_t queue = dispatch_queue_create(“com.example.gcd.barrier”, DISPATCH_QUEUE_CONCURRENT);
3     dispatch_async(queue, ^{
4         NSLog(@”read 0″);
5     });
6     dispatch_async(queue, ^{
7         NSLog(@”read 1″);
8     });
9     dispatch_async(queue, ^{
10         NSLog(@”read 2″);
11     });
12     dispatch_barrier_async(queue, ^{
13         NSLog(@”write”);
14     });
15     dispatch_async(queue, ^{
16         NSLog(@”read 3″);
17     });
18     dispatch_async(queue, ^{
19         NSLog(@”read 4″);
20     });
21     dispatch_async(queue, ^{
22         NSLog(@”read 5″);
23     });
24 }

这样就可以保证多次并发read

1 2020-04-29 17:45:00.149982+0800 GCDTest[56002:2263229] read 2
2 2020-04-29 17:45:00.149982+0800 GCDTest[56002:2263230] read 0
3 2020-04-29 17:45:00.149999+0800 GCDTest[56002:2263239] read 1
4 2020-04-29 17:45:00.150130+0800 GCDTest[56002:2263239] write
5 2020-04-29 17:45:00.150215+0800 GCDTest[56002:2263239] read 3
6 2020-04-29 17:45:00.150220+0800 GCDTest[56002:2263230] read 4
7 2020-04-29 17:45:00.150234+0800 GCDTest[56002:2263229] read 5

dispatch_apply
当我们需要将一个block加入到queue中,并多次执行时,使用dispatch_apply,dispatch_apply会阻塞当前线程,并等待queue执行完成。

1 – (void)dispatch_apply_test {
2     dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
3     dispatch_apply(10, queue, ^(size_t index) {
4         NSLog(@”%zu”,index);
5     });
6     NSLog(@”done”);
7 }

输出为:

1 2020-04-29 18:00:27.838731+0800 GCDTest[56107:2271775] 0
2 2020-04-29 18:00:27.838739+0800 GCDTest[56107:2271897] 1
3 2020-04-29 18:00:27.838739+0800 GCDTest[56107:2271893] 2
4 2020-04-29 18:00:27.838759+0800 GCDTest[56107:2271894] 3
5 2020-04-29 18:00:27.838858+0800 GCDTest[56107:2271897] 4
6 2020-04-29 18:00:27.838860+0800 GCDTest[56107:2271893] 5
7 2020-04-29 18:00:27.838861+0800 GCDTest[56107:2271894] 6
8 2020-04-29 18:00:27.838898+0800 GCDTest[56107:2271775] 7
9 2020-04-29 18:00:27.838941+0800 GCDTest[56107:2271897] 8
10 2020-04-29 18:00:27.838951+0800 GCDTest[56107:2271893] 9
11 2020-04-29 18:00:27.839616+0800 GCDTest[56107:2271775] done

dispatch_resume/dispatch_suspend
当多个task在Dispatch Queue中执行时,有时不想再继续执行了,可以使用dispatch_suspend将队列挂起。再使用dispatch_resume恢复,值得注意的是,并不能取消已经开始的任务。

对于想取消的线程,并能监听线程的各种状态,可以使用NSOperation和NSOperationQueue,还能够设置*大并发量。

NSOperation、NSOperationQueue 是苹果提供给我们的一套多线程解决方案。实际上 NSOperation、NSOperationQueue 是基于 GCD更高一层的封装,完全面向对象。但是比 GCD 更简单易用、代码可读性也更高。

可以添加任务依赖,方便控制执行顺序

可以设定操作执行的优先级

任务执行状态控制:isReady,isExecuting,isFinished,isCancelled

如果只是重写NSOperation的main方法,由底层控制变更任务执行及完成状态,以及任务退出
如果重写了NSOperation的start方法,自行控制任务状态
系统通过KVO的方式移除isFinished==YES的NSOperation

可以设置*大并发量
参考链接:https://www.jianshu.com/p/cbf759bdfd0f

dispatch TLS
线程TLS技术,Thread Local Storage(TLS)线程局部存储,目的很简单,将一块内存作为某个线程专有的存储,以key-value的形式进行读写,比如在非arm架构下,使用pthread提供的方法实现:

1  void* pthread_getspecific(pthread_key_t);
2  int pthread_setspecific(pthread_key_t , const void *);

GCD中也提供了相关的技术

1 #import <Foundation/Foundation.h>
2
3 static const void * const key1 = &key1;
4
5 int main(int argc, const char * argv[]) {
6     @autoreleasepool {
7         dispatch_queue_t queue1 = dispatch_queue_create(“com.ebebya.queue1”, NULL);
8         dispatch_queue_set_specific(queue1, key1, (void *)[@”ebebya” UTF8String], NULL);
9
10         dispatch_async(queue1, ^{
11             void *value = dispatch_get_specific(key1);
12             NSString *str = [[NSString alloc] initWithBytes:value length:7 encoding:4];
13             NSLog(@”%@”, str);
14         });
15     }
16     return 0;
17 }

但是是对于一个queue队列的上下文键值对,具体实现就不追究了。

友情链接: SITEMAP | 旋风加速器官网 | 旋风软件中心 | textarea | 黑洞加速器 | jiaohess | 老王加速器 | 烧饼哥加速器 | 小蓝鸟 | tiktok加速器 | 旋风加速度器 | 旋风加速 | quickq加速器 | 飞驰加速器 | 飞鸟加速器 | 狗急加速器 | hammer加速器 | trafficace | 原子加速器 | 葫芦加速器 | 麦旋风 | 油管加速器 | anycastly | INS加速器 | INS加速器免费版 | 免费vqn加速外网 | 旋风加速器 | 快橙加速器 | 啊哈加速器 | 迷雾通 | 优途加速器 | 海外播 | 坚果加速器 | 海外vqn加速 | 蘑菇加速器 | 毛豆加速器 | 接码平台 | 接码S | 西柚加速器 | 快柠檬加速器 | 黑洞加速 | falemon | 快橙加速器 | anycast加速器 | ibaidu | moneytreeblog | 坚果加速器 | 派币加速器 | 飞鸟加速器 | 毛豆APP | PIKPAK | 安卓vqn免费 | 一元机场加速器 | 一元机场 | 老王加速器 | 黑洞加速器 | 白石山 | 小牛加速器 | 黑洞加速 | 迷雾通官网 | 迷雾通 | 迷雾通加速器 | 十大免费加速神器 | 猎豹加速器 | 蚂蚁加速器 | 坚果加速器 | 黑洞加速 | 银河加速器 | 猎豹加速器 | 海鸥加速器 | 芒果加速器 | 小牛加速器 | 极光加速器 | 黑洞加速 | movabletype中文网 | 猎豹加速器官网 | 烧饼哥加速器官网 | 旋风加速器度器 | 哔咔漫画 | PicACG | 雷霆加速