1.?生命?????Դ??
2.画图带你彻底弄懂三级缓存和循环依赖的问题
3.SELF演讲实录 | 陈科:基因测序未来只需一千
4.搏杀生命带指标源码
5.LiveData 面试题库、解答、码生命代源码分析
6.Andorid进阶一:LeakCanary源码分析,源码从头到尾搞个明白
?生命?????Դ??
深入解析Android Framework源码,理解底层原理是码生命代Android开发者的关键。本文将带你快速入门Android Framework的源码源码安装ompl层次架构,从上至下分为四层,生命掌握Android系统启动流程,码生命代了解Binder的源码进程间通信机制,剖析Handler、生命AMS、码生命代WMS、源码Surface、生命SurfaceFlinger、码生命代PKMS、源码InputManagerService、DisplayManagerService等核心组件的工作原理。《Android Framework源码开发揭秘》学习手册,全面深入地讲解Android框架初始化过程及主要组件操作,适合有一定Android应用开发经验的开发者,旨在帮助开发者更好地理解Android应用程序设计与开发的核心概念和技术。通过本手册的学习,将能迅速掌握Android Framework的关键知识,为面试和实际项目提供有力支持。
系统启动流程分析覆盖了Android系统层次角度的三个阶段:Linux系统层、Android系统服务层、Zygote进程模型。理解这些阶段的关键知识,对于深入理解Android框架的启动过程至关重要。
Binder作为进程间通信的重要机制,在Android中扮演着驱动的角色。它支持多种进程间通信场景,包括系统类的打电话、闹钟等,以及自己创建的WebView、视频播放、音频播放、大图浏览等应用功能。
Handler源码解析,揭示了Android中事件处理机制的核心。深入理解Handler,对于构建响应式且高效的Android应用至关重要。
AMS(Activity Manager Service)源码解析,探究Activity管理和生命周期控制的原理。掌握AMS的实现细节,有助于优化应用的用户体验和性能。
WMS(Window Manager Service)源码解析,了解窗口管理、布局和显示策略的实现。深入理解WMS,对于构建美观且高效的用户界面至关重要。
Surface源码解析,揭示了图形渲染和显示管理的核心。Surface是Android系统中进行图形渲染和显示的基础组件,掌握其原理对于开发高质量的图形应用至关重要。
基于Android.0的SurfaceFlinger源码解析,探索图形渲染引擎的实现细节。SurfaceFlinger是Android系统中的图形渲染核心组件,理解其工作原理对于性能优化有极大帮助。
PKMS(Power Manager Service)源码解析,深入理解电池管理策略。掌握PKMS的实现,对于开发节能且响应迅速的应用至关重要。
InputManagerService源码解析,揭示了触摸、键盘输入等事件处理的核心机制。深入理解InputManagerService,对于构建响应式且用户体验优秀的应用至关重要。
DisplayManagerService源码解析,探究显示设备管理策略。了解DisplayManagerService的工作原理,有助于优化应用的显示性能和用户体验。
如果你对以上内容感兴趣,点击下方卡片即可免费领取《Android Framework源码开发揭秘》学习手册,开始你的Android框架深入学习之旅!
画图带你彻底弄懂三级缓存和循环依赖的问题
大家好。我们都知道,Spring可以通过三级缓存解决循环依赖的问题,这也是面试中很常见的一个面试题,本文就来着重讨论一下有关循环依赖和三级缓存的问题。一、什么是循环依赖大家平时在写业务的时候应该写过这样的代码。
其实这种类型就是循环依赖,就是AService 和BService两个类相互引用。
二、三级缓存可以解决的循环依赖场景如上面所说,大家平时在写这种代码的时候,项目其实是可以起来的,也就是说其实三级缓存是可以解决这种循环依赖的。
当然除了这种字段注入,set注入也是可以解决的,代码如下。
接下来就来探究三级缓存是如何解决这种循环依赖的?
三、Spring的Bean是如何创建出来的本文所说的Bean和对象可以理解为同一个意思。
先说如何解决循环依赖之前,先来了解一下一个Bean创建的大致流程。为什么要说Bean的创建过程,因为循环依赖主要是发生在Bean创建的过程中,知道Bean是乐兔淘源码如何创建的,才能更好的理解三级缓存的作用。
其实Spring Bean的生命周期源码剖析我也在微信公众号 三友的java日记 中发过,并且有简单的提到三级缓存,有兴趣的同学可以在关注公众号之后回复 Bean 即可获取文章链接,里面有Bean创建过程更详细的说明。这里我简单画一张图来说一下。
其实图里的每个阶段还可以分为一些小的阶段,我这里就没画出来了。
来说一下每个阶段干了什么事。
BeanDefinition的读取阶段:我们在往Spring容器注入Bean的时候,一般会通过比如xml方式,@Bean注解的方式,@Component注解的方式,其实不论哪一种,容器启动的时候都会去解析这些配置,然后为每个Bean生成一个对应的BeanDefinition,这个BeanDefinition包含了这个Bean的创建的信息,Spring就是根据BeanDefinition去决定如何创建一个符合你要求的Bean
Bean的实例化阶段:这个阶段主要是将你配置的Bean根据Class的类型创建一个对象出来
Bean的属性赋值阶段:这个阶段主要是用来处理属性的赋值,比如@Autowired注解的生效就是在这个阶段的
Bean的初始化阶段:这个阶段主要是回调一些方法,比如你的类实现了InitializingBean接口,那么就会回调afterPropertiesSet方法,同时动态代理其实也是在这个阶段完成的。
其实从这可以看出,一个Spring Bean的生成要分为很多的阶段,只有这些事都处理完了,这个Bean才是完完全全创建好的Bean,也就是我们可以使用的Bean。
四、三级缓存指的是哪三级缓存这里直接上源码
第一级缓存:singletonObjects
存放已经完完全全创建好的Bean,什么叫完完全全创建好的?就是上面说的是,所有的步骤都处理完了,就是创建好的Bean。一个Bean在产的过程中是需要经历很多的步骤,在这些步骤中可能要处理@Autowired注解,又或是处理@Transcational注解,当需要处理的都处理完之后的Bean,就是完完全全创建好的Bean,这个Bean是可以用来使用的,我们平时在用的Bean其实就是创建好的。
第二级缓存:earlySingletonObjects
早期暴露出去的Bean,其实也就是解决循环依赖的Bean。早期的意思就是没有完完全全创建好,但是由于有循环依赖,就需要把这种Bean提前暴露出去。其实 早期暴露出去的Bean 跟 完完全全创建好的Bean 他们是同一个对象,只不过早期Bean里面的注解可能还没处理,完完全全的Bean已经处理了完了,但是他们指的还是同一个对象,只不过它们是在Bean创建过程中处于的不同状态,如果早期暴露出去的Bean跟完完全全创建好的Bean不是同一个对象是会报错的,项目也就起不来,这个不一样导致报错问题,这里我会结合一个案例再来写一篇文章,这里不用太care,就认为是一样的。
第三级缓存:singletonFactories
存的是每个Bean对应的ObjectFactory对象,通过调用这个对象的getObject方法,就可以获取到早期暴露出去的Bean。
注意:这里有个很重要的细节就是三级缓存只会对单例的Bean生效,像多例的是无法利用到三级缓存的,通过三级缓存所在的类名DefaultSingletonBeanRegistry就可以看出,仅仅是对SingletonBean也就是单例Bean有效果。
五、三级缓存在Bean生成的过程中是如何解决循环依赖的这里我假设项目启动时先创建了AService的Bean,那么就会根据Spring Bean创建的过程来创建。
在Bean的实例化阶段,就会创建出AService的对象,此时里面的@Autowired注解是没有处理的,创建出AService的对象之后就会构建AService对应的一个ObjectFactory对象放到三级缓存中,通过这个ObjectFactory对象可以获取到AService的早期Bean。
然后AService继续往下走,到了某一个阶段,开始处理@Autowired注解,要注入BService对象,如图
要注入BService对象,肯定要去找BService对象,那么他就会从三级缓存中的第一级缓存开始依次查找有没有BService对应的Bean,肯定都没有啊,因为BService还没创建呢。没有该怎么办呢?其实很好办,没有就去创建一个么,这样不就有了么。于是AService的注入BService的过程就算暂停了,因为现在得去创建BService,创建之后才能注入给AService。
于是乎,BService就开始创建了,当然他也是Spring的Bean,所以也按照Bean的创建方式来创建,先实例化一个BService对象,然后缓存对应的一个ObjectFactory到第三级缓存中,然后就到了需要处理@Autowired注解的时候了,如图。
@Autowired注解需要注入AService对象。注入AService对象,就需要先去拿到AService对象,此时也会一次从三级缓存查有没有AService。
先从第一级查,dnf自动修理源码有没有创建好的AService,肯定没有,因为AService此时正在在创建(因为AService在创建的过程中需要注入BService才去创建BService的,虽然此刻代码正在创建BService,但是AService也是在创建的过程中,只不过暂停了,只要BService创建完,AService会继续往下创建);第一级缓存没有,那么就去第二级看看,也没有,没有早期的AService;然后去第三级缓存看看有没有AService对应的ObjectFactory对象,惊天的发现,竟然有(上面提到过,创建出AService的对象之后,会构建AService对应的一个ObjectFactory对象放到三级缓存中),那么此时就会调用AService对应的ObjectFactory对象的getObject方法,拿到早期的AService对象,然后将早期的AService对象放到二级缓存,为什么需要放到二级缓存,主要是怕还有其他的循环依赖,如果还有的话,直接从二级缓存中就能拿到早期的AService对象。
虽然是早期的AService对象,但是我前面说过,仅仅只是早期的AService对象可能有些Bean创建的步骤还没完成,跟最后完完全全创建好的AService Bean是同一个对象。
于是接下来就把早期的AService对象注入给BService。
此时BService的@Autowired注解注入AService对象就完成了,之后再经过其他阶段的处理之后,BService对象就完完全全的创建完了。
BService对象创建完之后,就会将BService放入第一级缓存,然后清空BService对应的第三级缓存,当然也会去清空第二级缓存,只是没有而已,至于为什么清空,很简单,因为BService已经完全创建好了,如果需要BService那就在第一级缓存中就能查找到,不需要在从第二级或者第三级缓存中找到早期的BService对象。
BService对象就完完全全的创建完之后,那么接下来该干什么呢?此时当然继续创建AService对象了,你不要忘了为什么需要创建BService对象,因为AService对象需要注入一个BService对象,所以才去创建BService的,那么此时既然BService已经创建完了,那么是不是就应该注入给AService对象了?所以就会将BService注入给AService对象,这下就明白了,BService在构建的时候,已经注入了AService,虽然是早期的AService,但的确是AService对象,现在又把BService注入给了AService,那么是不是已经解决了循环依赖的问题了,AService和BService都各自注入了对方,如图。
然后AService就会跟BService一样,继续处理其它阶段的,完全创建好之后,也会清空二三级缓存,放入第一级缓存。
到这里,AService和BService就都创建好了,循环依赖也就解决了。
这下你应该明白了三级缓存的作用,主要是第二级和第三级用来存早期的对象,这样在有循环依赖的对象,就可以注入另一个对象的早期状态,从而达到解决循环依赖的问题,而早期状态的对象,在构建完成之后,也就会成为完完全全可用的对象。
六、三级缓存无法解决的循环依赖场景1)构造器注入无法解决循环依赖上面的例子是通过@Autowired注解直接注入依赖的对象,但是如果通过构造器注入循环依赖的对象,是无法解决的,如代码下
构造器注入就是指创建AService对象的时候,就传入BService对象,而不是用@Autowired注解注入BService对象。
运行结果
启动时就会报错,所以通过构造器注入对象就能避免产生循环依赖的问题,因为如果有循环依赖的话,那么就会报错。
至于三级缓存为什么不能解决构造器注入的问题呢?其实很好理解,因为上面说三级缓存解决循环依赖的时候主要讲到,在AService实例化之后,会创建对应的ObjectFactory放到第三级缓存,发生循环依赖的时候,可以通过ObjectFactory拿到早期的AService对象;而构造器注入,是发生在实例化的时候,此时还没有AService对象正在创建,还没完成,压根就还没执行到往第三级添加对应的ObjectFactory的步骤,那么BService在创建的时候,就无法通过三级缓存拿到早期的AService对象,拿不到怎么办,那就去创建AService对象,但是度解剖dubbo源码AService不是正在创建么,于是会报错。
2)注入多例的对象无法解决循环依赖**启动引导类
要获取AService对象,因为多例的Bean在容器启动的时候是不会去创建的,所以得去获取,这样就会创建了。
运行结果
为什么不能解决,上面在说三级缓存的时候已经说过了,三级缓存只能对单例Bean生效,那么多例是不会起作用的,并且在创建Bean的时候有这么一个判断,那就是如果出现循环依赖并且是依赖的是多例的Bean,那么直接抛异常,源码如下
注释其实说的很明白,推测出现了循环依赖,抛异常。
所以上面提到的两种循环依赖的场景,之所以无法通过三级缓存来解决,是因为压根这两种场景就无法使用三级缓存,所以三级缓存肯定解决不掉。\
七、不用三级缓存,用二级缓存能不能解决循环依赖遇到这种面试题,你就跟面试官说,如果行的话,Spring的作者为什么不这么写呢?
哈哈,开个玩笑,接下来说说到底为什么不行。
这里我先说一下前面没提到的细节,那就是通过ObjectFactory获取的Bean可能是两种类型,第一种就是实例化阶段创建出来的对象,还是一种就是实例化阶段创建出来的对象的代理对象。至于是不是代理对象,取决于你的配置,如果添加了事务注解又或是自定义aop切面,那就需要代理。这里你不用担心,如果这里获取的是代理对象,那么最后完全创建好的对象也是代理对象,ObjectFactory获取的对象和最终完全创建好的还是同一个,不是同一个肯定会报错,所以上面的理论依然符合,这里只是更加的细节化。
有了这个知识点之后,我们就来谈一下为什么要三级缓存。
第一级缓存,也就是缓存完全创建好的Bean的缓存,这个缓存肯定是需要的,因为单例的Bean只能创建一次,那么肯定需要第一级缓存存储这些对象,如果有需要,直接从第一级缓存返回。那么如果只能有二级缓存的话,就只能舍弃第二级或者第三级缓存。
假设舍弃第三级缓存
舍弃第三级缓存,也就是没有ObjectFactory,那么就需要往第二缓存放入早期的Bean,那么是放没有代理的Bean还是被代理的Bean呢?
1)如果直接往二级缓存添加没有被代理的Bean,那么可能注入给其它对象的Bean跟最后最后完全生成的Bean是不一样的,因为最后生成的是代理对象,这肯定是不允许的;
2)那么如果直接往二级缓存添加一个代理Bean呢?
假设没有循环依赖,提前暴露了代理对象,那么如果跟最后创建好的不一样,那么项目启动就会报错,
假设没有循环依赖,使用了ObjectFactory,那么就不会提前暴露了代理对象,到最后生成的对象是什么就是什么,就不会报错,
如果有循环依赖,不论怎样都会提前暴露代理对象,那么如果跟最后创建好的不一样,那么项目启动就会报错
通过上面分析,如果没有循环依赖,使用ObjectFactory,就减少了提前暴露代理对象的可能性,从而减少报错的可能。
假设舍弃第二级缓存
假设舍弃第二级缓存,也就是没有存放早期的Bean的缓存,其实肯定也不行。上面说过,ObjectFactory其实获取的对象可能是代理的对象,那么如果每次都通过ObjectFactory获取代理对象,那么每次都重新创建一个代理对象,这肯定也是不允许的。
从上面分析,知道为什么不能使用二级缓存了吧,第三级缓存就是为了避免过早地创建代理对象,从而避免没有循环依赖过早暴露代理对象产生的问题,而第二级缓存就是防止多次创建代理对象,导致对象不同。
本文完。
如果觉得这篇文章对你有所帮助,还请帮忙点赞、在看、转发给更多的人,码字不易,非常感谢!
欢迎关注公众号 三友的博客主页html源码java日记,更多技术干货及时获得。原文:/post/SELF演讲实录 | 陈科:基因测序未来只需一千
小时经常会有人说,陈科你长得这么像你爸爸;也会有人说,陈科,你像你妈妈多一点。那为什么会这样呢?学过生物的人都知道,因为我们的DNA,也就是碱基,一半来自爸爸,一半来自妈妈。毫无疑问,我们的面貌特征是他们结合以后的体现。实际上,不仅仅体现在面貌上,我们的身高,我们的胖瘦,还有我们自己是否容易患上某种疾病,都跟我们的基因是密切关联的。我们来看一张万人迷的照片。我想大部分人对他都不会陌生,没错,他就是贝克汉姆。他从我们基因组学的术语来讲是由1×^个细胞组成。每一个细胞从外到内,分别由细胞膜、细胞浆和细胞核三大部分组成。
所谓的细胞核,顾名思义就是核心,是细胞最主要的成分,细胞是构成生命世界中每一个有机体的基本单位。那么细胞的细胞核再往下分是什么样的状态呢?这就是刚刚黎耕老师讲到的,年的时候人类发现DNA双螺旋结构。所以由大到小观察,从细胞核、染色体,再到DNA。DNA是最基本的单元,我们称之为碱基,它有ATGC四种类型。换句话说,我们是由这四种结构的DNA构成的。3.2×^9个碱基对,这就是我们人类基因组的DNA数目。
刚刚是从宏观到微观,从贝克汉姆到碱基DNA来进行观察;再反过来看看是怎样的过程?首先是四种DNA,最基本成分叫ATGC,他们形成一定的序列;再往上,有功能的序列我们称之为基因,基因与包含在基因周边的蛋白质,我们把它称为基因组;基因组构成了细胞核,细胞核是细胞的主要成分,细胞往上走,形成了器官,形成了系统;比如说我们的呼吸系统,血液系统,消化系统;到最后,贝克汉姆组装完毕,这就是由微观到宏观的过程。
这个过程的奇妙之处在哪儿呢?比如大家可能会问基因是什么、有什么作用?我们的生物学教科书里面有这样一个所谓的“中心法则”,从碱基或者说DNA开始,到RNA,到蛋白质,这个过程最终的目的是形成蛋白质。孩童的微笑,情侣之间的眉目传情,我在这里讲,您在下面听,所有的动作都是我们的蛋白质在执行功能。
DNA如此重要,它被称之为我们生命的源代码,这个源代码给予我们所有的活动,这些活动都能够回溯到DNA上去,因此我们可以从DNA中找到某种问题的原因,来解释它。
正是因为基因组的重要性,人类科学家开始联合起来进行研究。在上个世纪年代,确切来讲是年,以美国和英国为首的遗传学领域科学家们联合起来发起了人类基因组计划,这个计划简称叫HGP,由六国科学家组成。
当时计划用年的时间,测序一个人的基因组。为什么要花这么长的时间呢?因为我们基因组的大小是3.2×^9个序列,而且其中%以上是基因间区。换句话说它里面有很多的重复序列,这种重复序列的存在导致了我们想把它从3.2×^9的过程完全弄清楚是不太容易的。
人类基因组计划从年开始启动,到年,美国总统先生说我们完成了人类最伟大的计划之一,再到现在,这个版本已经更新到了第版,最新更新时间是年月。我们预计它的更新还会持续,只能说更新幅度越来越小,我们离真相越来越近。
自从人类基因组计划启动之后,相关测序产业也是蓬勃发展,直接作用就是我们可以了解更多物种的基因组是什么样子。到现在为止,有将近一万个物种已经有了自己的基因组。
不做基因组的人可能不太清楚,总统先生和黑猩猩有多少相似度?刚才猜测%、%、%、%的人都有,事实上是%。那么从基因组学这个角度来看,当我们认为自己多么与众不同时,多少显得有点滑稽。我们和猩猩的差别其实只有1%。而且,从更大范围来看,我们人类的基因组并不是最大的,我们的基因数目也不是最多的;最大的基因组来自于日本一种植物;这个表格中,平常不起眼的玉米,大概有5万个左右的基因,多于人类的2万个基因。中国人和美国人的基因相差只有0.1%,而我和你.%的基因都是一样的,差别不大。但是,回过头来要记住,因为它的基数是3.2×^9,你去乘基数之后,也就得到了^4到^5之间的差异。
我们经常会听到,不管是肿瘤也好,糖尿病也好,心脑血管疾病也好,经常都可以找到基因突变跟某一个疾病有关联的。但是请大家一定注意,很多情况只是一种关联,关联不是因果。因果是说,我和我老婆的存在,导致了我女儿的出生;而关联不是因果关系,只是一个随带的关系。比如我女儿碰巧上了这家幼儿园,她上这个幼儿园是一个关联,而不是因果。就像前面提到的一样,基因突变很多时候是一个关联;它并不可怕。而且我刚刚说了,哪怕我们.%相似,只有万分之一的不同,但是基数足够大。每个人,比如我们从爸爸妈妈继承的基因突变,每一代大概是个,这是有据可循的,而且这个里面大部分来自于父亲的贡献,有的遗传学家就此认为,其实进化的动力来自于父亲,因为它显现了更多突变,更有可能给后代带来基因的多样性,更有可能使得后代与众不同。
正是因为基因组学的如此重要,在人类基因组计划之后,全世界范围的科学家并没有放弃追逐。当时的人类基因计划研究对象只有一个人,但是一个人太少了,每个人都不一样,因此便有了后来的千人基因组计划,我们检测一下黄钟人,再测一下黑色人种,白色人种,每一个人种,不管是中国人,还是日本人,虽然差别可以缩小到十万分之一,但是它的数目还是足够大的。
所以千人基因组计划出台后,我们今后在使用的时候,在序列比对的时候,可能不用再去比人类基因组计划中的HG(人类基因组计划的第版),而是比对我们自己的,比对我们中国人群的,比对我们中国南方人群里面某一个亚系的人群基因组,这样才更有可能找到:我突变了什么?我哪种疾病爆发的可能性更大?这就是千人基因组计划的初衷。
后来,为了把一直困扰人类的癌症解释清楚,世界范围内的两大组织,分别是加拿大领衔的国际癌症基因组联盟和美国人领衔的癌症基因组图谱,用基因组学方法去测序某一个类别的肿瘤。
比如说肾癌,他们选择了多名肾癌患者来测序它的基因组,分析哪些肾癌产生了突变,哪些突变跟愈后相关联,哪些药物针对哪些突变,然后对患者后续治疗做指导。
美国人领衔的计划(TCGA)在去年结束,加拿大领衔计划(ICGC)现在还没有结束。但是毫无疑问,不管是白种人,黑种人,还是我们黄种人,我们人类最主要的肿瘤基本上都测序结束了,这就导致大量数据的产生。
我们知道一个U盘大概有十个G,乘以倍是个T,再乘以倍是个P。而我们研究所里面数据储存远远高于这个,因为数据无时无刻不在产生,这样的数据量意味着我们需要更大容量,需要更大的容器来把它装下来,不然我们没有办法去比对它,没有办法很好地使用它。而这也导致了所谓的生物大数据的出现,大到了T级,大到了P级。
在大数据的应用方面,精准医学的出现毫无疑问对大数据是最好的回馈。因为花了那么多的钱,十几个国家的科学家投入研究,十几年的时间,数百亿美金的投入,对我们人类产生了如此多的数据,我们不用它岂不变成了垃圾?其实精准医学并不仅仅是美国总统在年和年曾经提到,在这之前,在我们中国,在我们中国科学院,在美国以外的地方,很早就有人提出来精准医学,因为需要针对每个人的基因背景,针对每个人蛋白背景来做个性化的裁减,来做个性化的治疗,这就是所谓的精准医疗,形象点来说,就是哪里坏了修哪里,这是最好的想法。
这是精准医学在癌症领域的应用。我展示的这个流程图是以肝癌为例的整个精准医疗的流程。术前影像显示有个肿块,影像结果出来之后,大部分患者会选择做手术。手术之后我们会进行一个病理学的判断,诊断肝癌到哪一级,哪一期;并且对这样的手术样本进行基因组学建库,建库以后进行基因组学测序,测序之后进行分析,分析以后会由董事会(咨询委员会)坐下来讨论这个患者的基因背景是什么样的,哪些突变可能是致病的,哪些不是主要的突变,董事会(咨询委员会)里面会包含至少四类人员,包括生物信息学家、遗传学家、临床大夫、病理医生。讨论结束后,我们针对这些可用的突变频谱进行验证,验证结束之后我们会对患者进行报告。比如肝癌,已有的病理学分析到了哪个层面,现在基因组分析到了哪个状态,现在有哪些药可以用,哪些是针对患者的。这样的报告就是精准医学最直接的体现。
在国外,精准医疗已经在顶尖医院应用了大概5年左右的时间,但是精准医疗并没有完全的铺开,我们中国才刚刚起步。但是中国人从来都是勤奋的,国外需要一个月完成的流程,在我们中国天就可以搞定。
讲一个故事,这个故事的主角是华盛顿大学的一个助理教授,他自己做白血病研究。不幸的是,年的时候,他自己得上了白血病。按照以往的方法进行了化疗,但是5年过后病情复发,他移植了弟弟的骨髓,可是好景不长,三年之后他再次复发,而这个时候癌症基因组学的进展处在一个高峰阶段,癌症基因组学发现他有一个基因异常高表达,而且靶向药物可以治疗这个异常高表达基因。这里有一点特别强调的是,这个靶向药物其实是治疗晚期肾癌的。换句话说,他用治疗肾癌的药物治疗了白血病,那么现状如何呢?最近的资料显示他还活着。这是一个幸运儿,从开始治疗到现在已经过去了十二三年的时间,对于白血病患者来说,这是一个奇迹,对于肿瘤基因组学应用来说也是一个非常令人振奋的消息。
另一个例子与糖尿病有关。这位长者是斯坦福大学的教授,他自己也是做遗传学研究的,他的故事于年发表在Cell期刊--这是我们生物学研究人员最梦寐以求发文章的地方,可以理解为顶级期刊。他的故事讲到,在多天的时间里,他分个时段采集自己的血液做基因组的分析,他发现自己存在二型糖尿病的风险,这个风险值大概0.5左右,这个时候他就有点着急了,就像之前我们在网络上看到过的那样,安吉丽娜·朱莉因为家族罹患乳腺癌和卵巢癌的风险过大,就把乳腺全部切除了。当这位教授知道自身血糖升高之后,就开始进行行为干预,此后血糖降了下来。对于他来说精准医学是一个成功案例,因为它成功的延缓了自己糖尿病的进展,很有可能让自己的糖尿病发生时间延后,甚至不发生。
这是两个经典例子:一个是癌症,一个是糖尿病。这么好的例子,我们大部分人支付的起吗?答案是肯定的。年的时候,每个人做基因组测序的花费是亿美金,到了今天变成了一万元人民币,时间成本和人力成本直线式下降,年变成天,人力成本从三千人变成了三到五个人就能够搞定。所以现在一万块钱就可以测一个人的基因组,在今年年底这个费用还会继续下降,业界最终目标是一千块钱测一个人的基因组。也许5年左右的时间,我们可以用手机APP查看自己的基因组,享受生物大数据、基因组学数据、精准医疗带给大家的普惠,当然,在一定程度上,先期时候还是需要付费的。
正是因为生物数据的如此复杂多样,它的层次除了DNA,RNA,还有蛋白质,还有更多层面,这么多的数据,作为一个大夫来讲不可能完全记得的。对于我们绝大部分民众来说也没有必要记这个事情,因为有人替我们去做。
以IBM为代表的商业机构推出了所谓的电脑医生平台,这个平台最大的特点就是在秒之内搜索百万级别的文献,并给出一个相对合理的治疗方案。其中诊断阶段,治疗阶段,每个方案都有参考文献,不是凭空而来的,够强大吧?可能有人会担心,最后我们去医院看病可能医生不见了,可能被电脑替代了。事实上我可以很明确的告诉大家,不论今后怎么变,大夫必不可少,因为电脑所做的事情虽然如此强大,能够在秒内给出答案,但是这个答案仍基于已有的数据库,它没有推断的能力。
当然,如果说基于AlphaGO能够击败李世石这件事情,可以认为人工智能存在无限可能,但是至少从目前来看,电脑医生只是一个供人们搜索和检索的数据库,而不是一个具有推动、推算、推演能力、有逻辑思维能力的真正的人。所以大家想象的,到医院去对着一台机器说话,然后他告诉我去哪里检查,然后给我抽血、做按摩、做手术,这还需要很长的时间,但不能说绝对没有可能。
既然精准医疗是如此好的东西,为什么没有广泛推广?除了之前提到的费用原因,就我们国内状况来看,还有以下几个方面是需要进一步打破壁垒。
因为精准医疗是新事物,所以在监管层面还有很多东西没有理顺,没有一个真正条文规定告诉该怎么做,这是第一个方面。
第二个方面,对于患者来说,或者是对患者家属来说,他们非常想参与进来,但他们不知道有什么途径可以了解相关的信息。比如我把测序仪买回来,测序结果出来以后,医院也不会分析;如果我们依靠第三方机构,问题又来了,第三方机构鱼龙混杂,难以取信;甚至我们经常可以在街边巷尾看到这样的兜售行为,说给你家孩子测个基因,看看他未来适合做科学家、艺术家,还是适合当教师。这些到现在为止,因为我们的数据库不够强大,市面都是一些虚假的广告。
第四个层面,是目前还没有一家第三方机构能够把我前面提到的四种认证专家集中起来做这件事情,因为这个行业还处于起步阶段,还有很多需要完善的地方,但是曙光已经出现,今后的可能性很大。
我们人类从有史以来,死亡原因一直在变迁,多年前我们绝大部分的祖先都是因为饥饿和战乱而死亡,到了上个世纪上半叶,感染性疾病,西班牙流感,给人类留下巨大创伤,我们今天读教科书的时候仍然心有余悸;到了上个世纪下半叶,心脑血管疾病,癌症成为死亡的主要原因,有一些科学家医学预测,当我们解决这些问题之后,在即将到来的未来,神经系统疾病将成为我们人类即将消亡的原因。基因组学能够解决所有问题吗?答案是否定的。因为我们每个人的基因只有一套,但是基因上面所修饰的,所依附的,所被黏附在上面的分子是多种多样的。
时至今日,生命的天书已经被打开了,我们期待它给我们带来不一样的应用,最终造福于我们人类的健康,为我们人类谋更大的福祉,谢谢大家。谢谢中科院青促会对我个人成长的资助!
出品:中国科普博览SELF格致论道
登陆“SELF格致论道”官方网站获取更多信息(/)。本期视频也将陆续在中国科普博览上推出,敬请关注。更多合作与SELF工作组self@cnic.cn联系。
搏杀生命带指标源码
AMV0:=VOL*(O+C)/2;
BS:SUM(AMV0,)/SUM(VOL,),COLORFFFF,LINETHICK2;
STICKLINE(CLOSE>=OPEN,OPEN,CLOSE,5,1),COLORRED;
STICKLINE(OPEN>CLOSE,CLOSE,OPEN,5,0 ),COLORFF;
STICKLINE(CLOSE>=OPEN,CLOSE,HIGH,0.5 ,1 ),COLORRED;
STICKLINE(CLOSE>=OPEN,OPEN,LOW,0.5 ,1 ),COLORRED;
STICKLINE(OPEN>CLOSE,CLOSE,LOW,0.5 ,0 ),COLORFF;
STICKLINE(OPEN>CLOSE,OPEN,HIGH,0.5 ,0 ),COLORFF;
先试一下。
不满意的话,你也可以不要K线,只要彩带:
AMV0:=VOL*(O+C)/2;
BS:SUM(AMV0,)/SUM(VOL,),COLORFFFF,LINETHICK2;
把指标设置成主图指标就可以了。
LiveData 面试题库、解答、源码分析
LivaData 的面试题库与解答、源码分析 作者:唐子玄1. LiveData 如何感知生命周期的变化?
LiveData 在常规的观察者模式上附加了条件,若生命周期未达标,即使数据发生变化也不通知观察者。这通过 Lifecycle 实现,Lifecycle 是生命周期对应的类,提供了添加/移除生命周期观察者的方法,并定义了全部生命周期的状态及对应事件。要观察生命周期,需要实现 LifecycleEventObserver 接口,并注册给 Lifecycle。除了生命周期观察者外,还有数据观察者,数据观察者会与 LifecycleOwner 进行绑定。2. LiveData 是如何避免内存泄漏的?
内存泄漏是因为长生命周期的对象持有了短生命周期对象。在观察 LiveData 数据的代码中,Observer 作为界面的匿名内部类,它会持有界面的引用,同时 Observer 被 LiveData 持有,LivData 被 ViewModel 持有,而 ViewModel 的生命周期比 Activity 长。最终的持有链导致内存泄漏。LiveData 帮助避免内存泄漏,在内部 Observer 会被包装成 LifecycleBoundObserver,这实现了生命周期感知能力,同时它还持有了数据观察者,具备了数据观察能力。3. LiveData 是粘性的吗?若是,它是怎么做到的?
是的,LiveData 是粘性的。数据是持久的,意味着它不会因被消费而消失。当 LiveData 值更新时,会通知所有观察者。这一过程通过一个 Map 结构保存了所有观察者,并通过遍历 Map 并逐个调用 considerNotify() 方法实现。观察者会被包装在 LifecycleBoundObserver 中,它具备了生命周期感知能力,同时持有了数据观察者。当组件生命周期发生变化时,会尝试将最新值分发给该数据观察者。4. 粘性的 LiveData 会造成什么问题?怎么解决?
粘性的 LiveData 可能导致数据重复消费或消费逻辑混乱。解决方案包括使用带消费记录的值、带有最新版本号的观察者、SingleLiveEvent 等。其中,使用 SingleLiveEvent 可以根据数据的分类(暂态数据或非暂态数据)来选择性地利用或避免粘性。5. 什么情况下 LiveData 会丢失数据?
在高频数据更新的场景下使用 LiveData.postValue() 时,如果在这次调用和下次调用之间再次调用 postValue(),则会导致数据丢失,因为值先被缓存,再向主线程抛出分发值的任务。这与 LiveData 的设计和更新机制有关。6. 在 Fragment 中使用 LiveData 需注意些什么?
在 Fragment 中使用 LiveData 时,应当使用 viewLifecycleOwner 而非 this。避免因生命周期不一致导致的额外订阅者问题。使用 SingleLiveEvent 可以解决数据重复消费问题。7. 如何变换 LiveData 数据及注意事项?
androidx.lifecycle.Transformations 提供了变换 LiveData 数据的方法,如 map()。需要注意数据变换操作应避免阻塞主线程,可使用 CoroutineLiveData 来异步化数据变换。Andorid进阶一:LeakCanary源码分析,从头到尾搞个明白
内存优化掌握了吗?知道如何定位内存问题吗?面试官和蔼地问有些拘谨的小张。小张回答道:“就是用LeakCanary检测一下泄漏,找到对应泄漏的地方,修改错误的代码,回收没回收的引用,优化生命周期线程的依赖关系。”“那你了解LeakCanary分析内存泄漏的原理吗?”面试官追问。“不好意思,平时没有注意过。”小张心想:面试怎么总问这个,我只是一个普通的程序员。
前言:
应用性能优化是开发中不可或缺的一环,而内存优化尤为重要。内存泄漏导致的内存溢出崩溃和内存抖动带来的卡顿不流畅,都在切实影响着用户体验。LeakCanary常用于定位内存泄漏问题,是时候深入理解它的工作机制了。
名词理解:
hprof:hprof文件是Java的内存快照文件,格式后缀为.hprof,在LeakCanary中用于内存分析。WeakReference:弱引用,当对象仅被weak reference指向,没有任何其他strong reference指向时,在GC运行时,这个对象就会被回收,不论当前内存空间是否足够。在LeakCanary中用于监测被回收的无用对象是否被释放。Curtains:Square的另一个开源框架,用于处理Android窗口的集中式API,在LeakCanary中用于监测window rootView在detach后的内存泄漏。
目录:
本文将从以下几个方面进行分析:
一,怎么用?
查看官网文档可以看出,使用LeakCanary非常简单,只需添加相关依赖即可。debugImplementation只在debug模式的编译和最终的debug apk打包时有效。LeakCanary的初始化代码通过ContentProvider进行,会在AppWatcherInstaller类的oncreate方法中调用真正的初始化代码AppWatcher.manualInstall(application)。在AndroidManifest.xml中注册该provider,注册的ContentProvider会在application启动的时候自动回调oncreate方法。
二,官方阐述
安装LeakCanary后,它会通过4个步骤自动检测并报告内存泄漏:如果ObjectWatcher在等待5秒并运行垃圾收集后没有清除持有的弱引用,则被监视的对象被认为是保留的,并且可能会泄漏。LeakCanary会将其记录到Logcat中,并在泄漏列表展示中用Library Leak标签标记。LeakCanary附带一个已知泄漏的数据库,通过引用名称的模式匹配来识别泄漏,如Library Leaks。对于无法识别的泄漏,可以报告并自定义已知库泄漏的列表。
三,监测activity,fragment,rootView和viewmodel
初始化的代码关键在于AppWatcher作为Android平台使用ObjectWatcher封装的API中心,自动安装配置默认的监听。我们分析了四个默认监听的Watcher,包括ActivityWatcher,FragmentAndViewModelWatcher,RootViewWatcher和ServiceWatcher,分别用于监测activity,fragment,rootView和service的内存泄漏。
四,ObjectWatcher保留对象检查分析
LeakCanary通过ObjectWatcher监控内存泄漏,我们深入分析了其检查过程,包括创建弱引用,检查对应key对象的保留,以及内存快照转储和内存分析。
五,总结
本文全面分析了LeakCanary的实现原理,从安装、使用到内存泄漏的检测和分析,详细介绍了各个组件的作用和工作流程。通过深入理解LeakCanary,开发者可以更有效地定位和解决内存泄漏问题,优化应用性能。阅读源码不仅能深入了解LeakCanary的工作机制,还能学习到内存泄漏检测的通用方法和技巧。