精华内容
下载资源
问答
  • 那么,现在那些也想要自学java的伙伴们,肯定都关心一个问题如何系统的,全方面的自学java” 我所知道的,很多自学的小伙伴都放弃了,有的没办法后来参加培训去了。 为什么那么多人会中途放弃呢?因为自学真的不...

     

    我热爱自学,觉得自学是一条逆袭之路!

    我现在主要从事java开发工作,我所掌握的java技能都是自学得来的,从大学开始到现在,我想未来,自己依然会持续自学,不单单是java,可能是方方面面的技能,只要是能提高自己的,让自己的活的更精彩的!

    那么,现在那些也想要自学java的伙伴们,肯定都关心一个问题“如何系统的,全方面的自学java

    我所知道的,很多自学的小伙伴都放弃了,有的没办法后来参加培训去了。

    为什么那么多人会中途放弃呢?因为自学真的不容易,比如在自学的过程中遇到问题无人请教,觉得自己的付出与收获不成正比,学了很多觉得自己会的很少等等!这些苦,只有真正自学过的人才懂得!

    想必在你决定自学的那一刻,你就比较关注关于自学的方方面面,希望从过来人的身上获得一些宝贵经验,希望自己的自学之路不那么坎坷,所以你很关注那些什么高效自学方法,什么自学秘籍等等,这些对你很有吸引力!

    的确,我也一直是一个信奉方法论的人,在这方面,我也看了很多别人所谓的自学秘籍,高效方法,看后,让我觉得很多有用的寥寥无几,觉得都是在吹嘘一些高大上的概念,说一些不知道有的没的所谓的心理学概念,都啥玩意啊!

    其实,关于自学编程,有一个通用的方法就是“多花时间,多练习,多敲代码”,这其实就是最简单而又最高效的学习方法,只不过你们觉得太过于普通,没啥吸引力,这不是你们想要的独门秘籍,因为这个大家都知道,并不能让你很快的成为大多自学者中的佼佼者!

    那么我们该如何系统的,全方面的自学Java呢?

    我们这里提到了系统,全方面,这是因为很多人的学习其实都是零散的,不成体系的,应该有不少的人是这样的一种学习模式,今天看到这个技术就去学,明天听到那个技术就又去学,都是东一棒头,西一榔头的,时间长了,觉得自己学的不少,但是感觉乱巴巴的,而且过不了多久就发现,自己忘得差不多了。

    是的,自学中一个强大的拦路虎,那就是遗忘,想必很多人都有这样的体会,很多知识,当时觉得自己掌握的很不错,可是时间没过多久自己就忘得差不多了,这其实是一件很打击自己自信心的事情。

    知识的散乱不成体系,学过很容易遗忘,不知道该学什么,学了很多也觉得空荡荡的,等等,这都是我们在自学中会遇到的问题,那么该如何解决?

    我今天就分享下我的方法,不是什么高大上的独门秘籍,其实就是很平常的做法,只不过没有一个人系统的给你说说,那么今天就由我来告诉你吧!

    首先我想先给那些完全零基础开始自学java的朋友说说,你们该怎么开始,对于你们这样的,你们就记住了,找一本学习java的书籍或者找一套java视频教程,然后从前到后,完完整整的学一遍再说,其他的啥也别讲,你这个时候就一门心思的看这本书或者这套视频教程,遇到不懂得百度,实在不懂得记下来先放着,继续往下学。

    记住一切以学完这套视频教程或者书为主(如果你没有学习视频教程,可以加我的微信mashibing08,我给你,另外我也正在写一套完全针对小白的java自学教程,目前正在连载中,我想很适合你)

    然后下面我想要说的就是,无论你是完全零基础还是有基础,那都适合你,以下要说的也是本次分享的重中之重!

    你可以想一下,如果我们所学过的每个知识,学了就不会忘记的话,那我们就超神啦,当然这是不可能的事情,我们一定会忘记,不然你就成精了,所以嘞我们所说的这些什么高效方法的目的,我觉得应该就是朝着这个方向去努力。

    那么该怎么朝这个方向努力?我们该如何保证我们在不断学习新知识的情况下使得我们对知识的遗忘尽量尽量变得缓慢?还有就是如果我们对以往学习过得知识遗忘了,该怎么快速找回?

    这才应该是我们每个人都希望以及都应该得到的学习秘籍啊!

    那咋做啊,别卖关子了行吗?其实很简单啊,很早我们就听过一句话啊“好记性不如烂笔头”,知道是啥了吧?那就是记笔记啊,学习过程中一定要笔记的,就这么简单?

    当然还有另外一句“温故而知新”,这不是就是经常复习吗?

    记笔记然后多复习?就这样?可能有人觉得不满意了,这啥啊?

    当然不止如此,不过核心就是记笔记+常复习,除此之外,还有很重要的几个点,且听我细细道来!

    首先是关于记笔记,这里记笔记可是有讲究的,可不是简单学到一个知识点记下重点那么简单,我这里所说的记笔记非常关键的一个点就是,对于这个知识点你一定要有自己的思考与理解,然后经过自己的思考和理解之后,把自己对于这个知识点的思考和理解用自己的话写出来,这才是我这里说的记笔记,而且对于一些很重要的知识点,比如是核心,面试经常考查,对理解其他知识点很有帮助之类的,那你就要花大功夫,多花时间去学习,然后经过自己的不断思考和理解,把它写成一篇以自己理解为主的博客。

    这个就是我心目中最完美的笔记!

    那么这篇笔记写完之后该怎么办呢?因为这已经是一个完整的对某个知识点详细分析了,你完全可以把它发布在一些社交平台,比如CSDN,掘金,知乎或者博客园,只要你喜欢,你都可以分享,对的,这就是在写博客,至于写博客有哪些好处我就不多说了,你可以搜索一下“写博客的好处”,不过我还是要说一点,当你把你的笔记分享出去,那么就会有别人看到,可能有人喷你写的什么玩意,也可能有人给你个赞,当然也会有人给你说哪里哪里写的不对,你看,这对你就是成长的绝佳机会啊!

    注意啦!发布到社交平台是一部分,还有很重要的一点就是你本地要保留,本地该怎么保留呢?

    我们程序员现在写笔记啊,特别是这种完整的博客型笔记,我们一般都会用markdown来写,然后保存到本地,这里特别要注意,我们写笔记和保存笔记都要注重系统性完整性,什么意思嘞,给你们看看我的,比如我的关于数据结构和算法的学习笔记都保存在这一个文件中

     

    然后关于数据结构和算法的知识点,每一个我都会认真学习,然后经过自己的思考和理解,写成博客型笔记,给你们看看
    在这里插入图片描述
    不知道你们注意没,这里的笔记顺序一般就是按照数据结构与算法的学习顺序去写的,这也就是保证了系统性和完整性。

    还有一点我想强调一下,大家对自己学习某个知识点写的笔记一定要认真对待,我对自己的要求就是,每一篇都要加入自己大量的思考与理解,每一篇都要是精品! 这可都是自己的知识财富啊!

    这就是关于记笔记我要说的,你看看,和你理解的记笔记是不是不一样呢?

    那剩下就是关于常复习了!

    这个就简单了,有了之前的记笔记,这里就顺理成章了,经过我们上面记笔记那一步,我们把自己的学习笔记整理的系统而完整,为啥要这样,因为无论你学习某一个知识点,当初是多么的用功,理解的是多么透彻,笔记是有多详细,我想你肯定会出现过不了多久就忘记的现象,这太正常了,之前也说过了,不然你就成精了啊!

    可是现在我们忘了也不怕,我们有系统且完整的笔记啊,我们不仅可以时常去复习,当我们对某一个自己之前学习过的知识点有遗忘的现象,我们可以马上拿出自己之前记得这些笔记,好好看看,保证不会花费你太多时间,而且能让你记起大部分的知识,为啥,因为这些知识都是自己之前经过大量的思考与理解形成的,就是我们自己的东西,后期看一下就能马上理解!

    这也是我为什么强烈要求你记笔记一定要经过自己的思考和理解的重要原因!

    你看,哪天我发现自己对哈希表有点模糊了,没事拿出自己的笔记复习吧,快速且高效,有时候还会悟出新的东西,真爽!

    好啦,这就是我对如何系统的,全方面的学习java的一些见解,希望对你们有用!谢谢!

    感谢阅读

    大学的时候选择了自学Java,工作了发现吃了计算机基础不好的亏,学历不行这是没办法的事,只能后天弥补,于是不断的学习Java核心知识,深入的研习计算机基础知识,所有心得全部书写成文,整理成有目录的PDF,持续原创,不断成长吧!

    其实这里不仅有技术,更有那些技术之外的东西,比如,如何做一个精致的程序员,而不是“屌丝”,程序员本身就是高贵的一种存在啊,难道不是吗?

    非常欢迎你的加入,未来的日子,有你有我,一起做一个人不傻,钱很多,活得久的快乐的程序员吧!

     

    任何问题,可以加微信:mashibing08,另外,我有个交流群,我会***不定期在群里分享学习资源,不定时福利***,感兴趣的可以说下我邀请你!

    对了,如果你是个Java小白的话,也可以加我微信,我相信你在学习的过程中一定遇到不少问题,或许我可以帮助你,毕竟我也是过来人了!

    喜欢对你有帮助的话记得加个关注不迷路哦

    个人主页有领取方式,可以领取到一些个人收集的面试及电子书资料,或许对你有帮助!

    《Java学习、面试;文档、视频资源免费获取》

    感谢各位大大的阅读🥰

    展开全文
  • 每一次容器申请失败直接造成研发测试停滞, 同时带来答疑及问题排查(程序猿最怕的就是在代码写正嗨的时候被人给打断,所以一般我都带耳机),涉及到测试链路上各个系统。随着集团pouch化的全面推进,半年来测试环境...

    痛点

    每一次容器申请失败直接造成研发测试停滞, 同时带来答疑及问题排查(程序猿最怕的就是在代码写得正嗨的时候被人给打断,所以一般我都带耳机),涉及到测试链路上各个系统。随着集团pouch化的全面推进,半年来测试环境日容器申请量暴增10倍以上,低成功率导致研发低效的问题越来越凸显,每天累计造成集团上百小时的研发测试停滞,损失不可接受,也渐渐成为了pouch化推进过程中的一个阻力。

    因此, 测试环境稳定性亟待大幅提升。经过答疑汇总和错误分析,主要集中在两个方面:

    已成功申请的资源不可用

    • 测试环境宿主机较差(过保机器),且虚拟比高,容易发生故障。
    • 宿主机故障时,其上的容器不会被自动迁移,很可能导致再次部署重启时失败。
    • 调度系统巡检会将故障宿主机置为不可调度,由于其上仍有容器,不能下线修复后重用, 造成机器资源越来越少。

    新申请资源时成功率低

    • 测试环境机器被分为优先级不同的资源池,资源池间机器资源不共享。
    • 测试环境机器的容量/余量不透明,没有告警,造成因资源不足的调度失败。
    • 因为测试环境与线上环境有很大不同,资源调度系统之前没有针对测试场景优化, 成功率不高。

    目标

    容器申请成功率:99.9%

    方案

    baac5bbce70d70c9b57c71123e64eee1c0c45f06

    指标数据

    从一开始我们就觉的数据非常重要,没有相关的稳定性数据,那我们就无的放矢,根据数据我们就能找到需要优化的点以及持续优化的动力。所以项目开始阶段就做了挺长时间的数据收集工作。

    • 测试环境链路数据收集:从上至下包括Normandy(基础应用运维平台),黄蜂(资源申请平台),Zeus(二层调度),Sigma(集团资源调度系统);其中我们最关心的就是最终容器交付的成功率,以及失败case。失败case可以帮助我们分析整个系统中到底哪些地方存在问题,成功率趋势则帮助我们检验新的修复优化是否真的有效且稳定,也是最终成果的衡量指标。
    • 测试环境链路稳定性数据展示平台:其实上下游的每个系统都有自己的数据,但是没有整合,有的用阿里表哥,有的是发邮件,有的则没有展示出来,所以做这样一个小东西的目的就是将上下游系统的数据统一整合在一个页面上,更便于查看分析问题
    • 每日/周/月错误分析:收集每天的错误数量及样例,便于分析问题。

    已申请容器不可用

    容器自动置换

    容器自动置换是为了解决已申请的容器不可用问题,简单来说就是在另一台好的宿主机上扩一个新容器,然后将原来在故障宿主机上的旧容器下线。

    整个流程如下:Sigma(资源调度系统)自动巡检出故障宿主机(比如磁盘满/硬件故障等),通知Atom(故障机替换)置换该故障宿主机上容器,Atom向Normandy(基础应用运维平台)发起机器置换流程。

    通过自动置换将故障机腾空,然后下线修复。

    新申请容器失败

    合理化资源池分配

    24de4f6c7e0d70e1344c81695f4cc5e7da5ed013

    屏蔽底层系统失败

    因为测试环境与线上环境差异很大,一般测试环境使用的机器都是线上淘汰机,同时为了节省预算,每台宿主机的虚拟比都很高,导致在创建和使用容器时都特别容易失败,所以有必要做一个容器buffer池屏蔽掉底层失败对用户的影响。

    buffer池的整个逻辑非常简单清晰:在测试环境容器生产链路靠近用户的一端嵌入buffer池,预生产一批容器,在用户需要的时候分配给他。即使申请buffer容器失败,依然可以按原生产链路继续生产容器。每次从buffer池申请一个容器后,buffer池会自动异步补充一个相同规格的容器进来,以维持buffer池的容量。

    如何确定buffer哪些规格的容器及池子的容量是另一个关键点:需要统计每种规格-镜像-资源池的历史申请量,按比例分配每种buffer的容量。同时为了保证即使在底层系统中断服务时,整个系统依然对用户可用,还需要确定高峰期的容器申请量,可允许中断时长以及测试环境机器资源, 用来确定整个buffer池子的容量。

    还需要考虑的一点是,用户也分为普通用户(研发测试人员),系统用户(比如自动化测试系统等),他们的优先级也不同,需要优先保证普通用户可用。

    同时为了最大程度的降低引入buffer池后可能对用户造成的影响,buffer池内加了许多动态开关,用于及时屏蔽某些功能。比如可针对具体应用设置是否需要修改容器主机名,此操作非常耗时,如果不改主机名,则平均不到1秒内会申请成功;如果某个应用不想使用buffer,也可立即屏蔽;如果buffer池本身出现问题,可以快速降级,在整个链路中去掉buffer功能。

    另外buffer池在交付buffer容器前会额外做一次检查,判断容器是否可用,避免容器交付后,因为容器不可用而导致的服务部署失败,用户使用不了等问题。buffer池内部也会定期清理脏容器(不可用, 数据不一致等)和补充新的buffer容器。

    总结

    41169ee82b713fbc3ffbf53caf4599646dd8ce90

    上图展示测试环境最近2个月的容器申请成功率趋势,包括buffer池全量前后一个月。

    从图中可以看到,11月末12月初的两天成功率极低,均是因为调度失败,之后根据资源池余量预测及报警及时调整了各个资源池的容量,提前消除了调度失败的可能,在此之后,成功率波幅都减少很多。

    另一点,从buffer全量后,成功率波幅明显比buffer全量前大幅减小,波动次数明显减少,成功率趋于稳定。

    buffer池全量后的一周内,由于buffer池内部的bug以及buffer命中率较低,成功率浮动较大,在bug修复以及提高buffer池命中率后,成功率基本稳定。

    200a027192ee745022f5ef128fdde3795b1df9bc

    上图展示近两个月的每日成功率趋势图,纵向对比了用户视角(有buffer)与底层系统视角(无buffer)。从图中可以看出,buffer池确实屏蔽了许多底层系统失败,除了其中一天buffer池被穿透导致成功率大跌。

    展望

    虽然经过一系列改造优化后,成功率有了明显的提升,但是依然有很多地方需要完善:

    • 资源池容量自动调配:目前算法简单,有些情况无法解决,比如大规模的新增或删除容器造成对余量趋势的误判。另外也要避免引入自动调配后造成宿主机标签的混乱。
    • buffer池模版动态的增减以及每种buffer的数量动态变化。当前buffer池一个难题就是如何覆盖到低频的应用镜像,这种镜像虽然低频但是容易申请失败,一旦这种容器大量申请,容易穿透buffer池,造成大量失败。
    • 扩大buffer池的容量,需要根据机器资源伸缩。

    除了对以前工作的完善,测试环境依然有许多要做的事情:比如如何提高整个测试环境资源的利用率, 如何减少容器交付耗时(从用户申请到用户可用),如何推动应用的可调度化等等,希望能够和大家一起探讨。


    原文发布时间为:2018-03-5

    本文作者:张劲

    本文来自云栖社区合作伙伴“阿里技术”,了解相关信息可以关注“阿里技术”微信公众号

    展开全文
  • 全面理解Handler-1:理解消息队列,手写消息队列 今天我们来聊一聊上文中还未作出解答的问题。作为死循环的loop,如何做到不阻塞住我们的生命周期。(~文末有福利~) 正文 一、死循环 首先,我们弄清死循环的意义。...

    前言

    上文我们聊了Handler机制出现的道理,以及消息队列的写法。

    全面理解Handler-1:理解消息队列,手写消息队列

    今天我们来聊一聊上文中还未作出解答的问题。作为死循环的loop,如何做到不阻塞住我们的生命周期。(~文末有福利~)

    正文

    一、死循环

    首先,我们得弄清死循环的意义。我们都明白,对于线程来说。代码的结束也就意味的线程生命的终止。想要获得“永生”,那么该怎么做?很显然,只要代码永远执行不完就可以了。既然如此,那么死循环显然非常符合这个要求:

    while(true){
    	// 我是不朽的~!
    }
    复制代码

    这样我们就弄清楚了loop()死循环的意义之一。 但是随之而来,引入了全新的问题:既然是死循环,那么循环体之外的代码势必不会被执行。

    为了能够正常的运行程序,我们就要想办法在循环体内调度其他方法。start其他线程,通过消息队列轮询。这显然是一个不错的方案,主线程的循环体只需要源源不断的从消息队列中取消息,执行就可以了。至于消息从哪里来,从哪个线程来这个不重要,一点都不重要。

    Handler机制的一个作用就出来了:实现不同线程间的数据传递(这里传递是Message,其他线程往MessageQueue发送Message,主线程轮询取出并执行)。

    有了这个思想,我们来想想对于Android来说是一个怎样的实现。

    1.1、Android中的死循环

    显然ActivityThread中,main方法里调用的loop()就是这个死循环体。

    public static void loop() {
    	//省略部分代码
        for (;;) {
    	    //省略部分代码
        }
    }
    复制代码

    有了上边的分析,我们就能够明白:

    • 1、它的存在保证了我们主线程的不死不灭。
    • 2、而Handler机制保证了我们线程之间消息的调度。

    死循环的意义我们明白了。那么死循环为什么阻塞不住我们的UI线程?一句话先来概括一下:

    真正会卡死主线程的操作是,在onCreate/onStart/onResume等这种生命周期方法中执行了耗时操作,而非loop死循环。 只要我们组件的生命周期正常被回调,那么loop死不死循环,对我们没有任何影响。因为我们的代码逻辑全部是在对应的生命周期中执行了。

    那么问题就来了:**组件的生命周期方法是怎么被回调的?**回答这个问题之前,让我们好好捋一捋Handler机制的设计:

    1.2、Handler机制的思路

    主线程持有MessageQueue,loop()死循环从MessageQueue中不断的取出Message,不为null,就执行Message中对应的方法。其他线程通过LocalThread拿到MessageQueue,进而就可以往Queue中发送Message。

    有了这个思路其实我们就可以回答这个问题:组件的生命周期方法是怎么被回调的?

    答案是:只需要在生命周期方法该被回调的时候,在其他线程中,通过往MessageQueue中发送Message的形式,就可以告知主线程,该回调对应的生命周期方法了。

    当然用文字表达很简单。实际落实到代码中就涉及很多内容了。因此接下来让我们真正的从代码中看生命周期方法是如何被调度的。

    二、生命周期的调度

    2.1、简述流程

    要想弄清楚生命周期的调度,这里不得不提起一个名词:Binder机制。而且这其中还涉及到了我们一定耳濡目染过的流程,先看一张图:

    对于上图来说。进程俩端,一个是Binder客户端一个是Binder服务端。简单来说,服务端用于响应客户端的调用。

    因此对于上图来说,App默认进程中的ApplicationThread就是Binder的客户端,用于响应system_server进程中Binder客户端ApplicationThreadProxy的调用。

    同理,system_server进程中Binder客户端ActivityManagerService就是响应App默认进程中Binder客户端的ActivityManagerProxy对象的调用。

    2.2、Handler + Binder

    在2.1中我们用一张图一段话聊了Binder机制。有了这个基础,我们就可以在结合Handler机制,解释一下我们的生命周期是如何被调度的了。

    对于Activity来说,它的生命周期一定是在主线程中被回调。那么此过程就是通过Handler机制的方式实现的。我们简单上一下ActivityThread中的一段代码,后文会着重分析:

    private class H extends Handler {
        // 省略部分代码
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case RESUME_ACTIVITY:
                    handleResumeActivity((IBinder) msg.obj, true, msg.arg1 != 0, true);
                    break;
                }
        }
    }
    复制代码

    最开始我们分析了,Handler的轮询在loop这个死循环里。想要保证源源不断的Message那么势必要启动额外的线程。而我们的ActivityManagerProxy就是额外的线程。它在loop()调用前被启动:

    Looper.prepareMainLooper();
    
    ActivityThread thread = new ActivityThread(); 
    //建立Binder通道,也就是创建新线程
    thread.attach(false);
    
    Looper.loop();
    复制代码

    简单来说,比如我们想要执行某Activity的onResume()方法。流程是这样的:

    用文字简单解释一下: 通过ActivityManagerProxy(App默认进程),通过Binder传输到ActivityManagerService中,ActivityManagerService再通过同进程的ApplicationThreadProxy(system_server进程)通过Binder传输到ApplicationThread(App默认进程)之中,此时已经来到了我们的App默认进程中的BInder线程中。那么此时就可以通过Handler机制,将Message发送给主线程了,再由主线程找到对应的Activity实例,回调对应的onResume方法。

    三、Read F**k Code

    3.1、Binder线程的启动

    我们先来看一下上文提到的attch方法:

    private void attach(boolean system) {
        final IActivityManager mgr = ActivityManager.getService();
        try {
            mgr.attachApplication(mAppThread);
        } catch (RemoteException ex) {
            throw ex.rethrowFromSystemServer();
        }
    }
    复制代码

    IActivityManager是IActivityManager,aidl的接口类。那它具体的对象是谁?

    public static IActivityManager getService() {
        return IActivityManagerSingleton.get();
    }
    
    private static final Singleton<IActivityManager> IActivityManagerSingleton =
        new Singleton<IActivityManager>() {
            @Override
            protected IActivityManager create() {
                final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
                final IActivityManager am = IActivityManager.Stub.asInterface(b);
                return am;
            }
    	};
    复制代码

    很明显我们需要追到ServiceManager中一探究竟:

    private static HashMap<String, IBinder> sCache = new HashMap<String, IBinder>();
    
    public static IBinder getService(String name) {
    	// 省略部分代码
    	IBinder service = sCache.get(name);
    }
    复制代码

    我们可以看到这里通过HashMap去查多赢的IBinder对象。那我们就来看看这个key为Context.ACTIVITY_SERVICE的value是谁:

    ActivityManagerService{
    	// 省略部分代码
    	ServiceManager.addService(Context.ACTIVITY_SERVICE, this, true);
    }
    复制代码

    那么此时我们也就知道IActivityManager 对象具体是谁了,真相只有一个ActivityManagerProxy。因为IActivityManager.Stub.asInterface(b)会根据当前进程情况来决定是返回Stub对象还是Proxy对象。我们的AMS运行在另一个进程那么此时返回的就是Proxy对象。

    此时,我们的额外的线程就创建完毕了。有了这个线程我们就可以来在loop外去相应四大组件的生命周期回调了。

    3.2、H

    因为本篇的重点是Handler里,所以这里跳过Binder的过程,我们直接假设,ApplicationThreadProxy通过Binder调用了我们的ApplicationThread对象。

    private class ApplicationThread extends IApplicationThread.Stub {
    	// 省略部分代码
    	public final void scheduleResumeActivity(IBinder token, int processState,
                    boolean isForward, Bundle resumeArgs) {
            // 省略部分代码
            sendMessage(H.RESUME_ACTIVITY, token, isForward ? 1 : 0, 0, seq);
        }
    }
    复制代码

    此时我们可以很清晰的看到,在scheduleResumeActivity方法中,使用了sendMessage方法,很明显这是一个封装的方法。让我们进去看那一看:

    private void sendMessage(int what, Object obj, int arg1, int arg2, int seq) {
            if (DEBUG_MESSAGES) Slog.v(
                    TAG, "SCHEDULE " + mH.codeToString(what) + " arg1=" + arg1 + " arg2=" + arg2 +
                            "seq= " + seq);
            Message msg = Message.obtain();
            // 省略部分代码
            mH.sendMessage(msg);
        }
    复制代码

    这里我们能够看到一个特别的Handler实现类H。说白了就是主线程中声明的一个Handler而已

    private class H extends Handler {
        // 省略部分代码
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case RESUME_ACTIVITY:
                    handleResumeActivity((IBinder) msg.obj, true, msg.arg1 != 0, true);
                    break;
                }
        }
    }
    复制代码

    此时我们就能够看到,我们Activity的生命周期完成了调用。

    final void handleResumeActivity(IBinder token,
                boolean clearHide, boolean isForward, boolean reallyResume, int seq, String reason) {
            ActivityClientRecord r = mActivities.get(token);
            // 省略部分代码
            r = performResumeActivity(token, clearHide, reason);
    }
    复制代码

    四、总结

    我所疑惑的点,无非是下面这几个。现在已经解释的通了。

    4.1、loop死循环的意义

    对于线程来说,代码执行结束,线程消失。那么对于主线程来说,想要不死,死循环首选。

    4.2、死循环如何保证声明周期的调度

    这里主要是通过Binder机制。在loop被调用前,会启动一个Binder线程。当我们想要调用某个组件的生命周期方法时,通过Binder机制,交由ActivityManagerService(AMS)去处理,最终仍通过Binder机制回传给我们的ApplicationThread对象。这个对象最终听过Handler将调度的Message发送到主线程的MessageQueue里,完成生命周期的正常调度。

    尾声

    到此关于我对Handler想写的内容就正式结束了,当然这其中仍有很多的坑还没有填

    • 比如:Linux pipe/epoll机制

    • 比如:篇幅比较长的Binder,关于Binder会在接下来的文章中出现。

    此外这篇文中分析的过程更多的有点像Activity的启动过程。接下来关于Binder的文章,有真正的以启动Activity为例子,把Binder机制串起来~

    哈哈,没有福利~

    我是一个应届生,最近和朋友们维护了一个公众号,内容是我们在从应届生过渡到开发这一路所踩过的坑,以及我们一步步学习的记录,如果感兴趣的朋友可以关注一下,一同加油~

    展开全文
  • 2018年7月09日,微信小程序流量主全面开通,(开发者...微信小游戏可以申请视频广告(一般小游戏为了激励用户观看广告都会推出视频金币/积分这类的东西)玩过微信小游戏应该都晓得吧?最近我也是刚刚研究微信小

    2018年7月09日,微信小程序流量主全面开通,(开发者福音)

    在这里插入图片描述

    开通条件如下:累计独立访客(UV)不低于1000 # 一共一千个人访问你的小程序就可以申请(不限时间)

    有严重违规记录的小程序不予申请  # 这个你不做什么伤天害理的事情应该是托托没问题得!

    目前个人小程序只支持申请Banner广告(横幅),

    微信小游戏可以申请视频广告(一般小游戏为了激励用户观看广告都会推出看视频得金币/积分这类的东西)玩过微信小游戏得应该都晓得吧?最近我也是刚刚研究微信小程序,(会开发)朋友整的一小程序~~~ 审核挺快的,一般就是1~2天左右。

    以下是我自己业余时间做的一个小程序,欢迎大家光临使用。

    也有大型商业项目小程序就不展示啦,保密协议原因——望见谅(有点装逼啦,哈哈哈哈?)。
    在这里插入图片描述

    展开全文
  • 写作背景:了些视频,网上也了很多篇文章,感觉写都很片面,不是很全,所以我整体总结了一些,我不喜欢重复造轮子,对于网上很多篇复制机类型的文章(很多文章所有字体相同)且很多不正确严重误导他人,我很是...
  • 这是一个有趣的问题,我认为我们都可以是伟大的程序员,无论我们的天赋如何,如果我们遵循一些规则的话——我相信——这应该是常识。实际上,这些规则并不只适用于编程领域,也适合任何专业。 当然,这些要点中的...
  • 如何学习?

    千次阅读 2016-03-22 15:42:51
    最近有朋友私下问如何学习的问题,我感觉这个问题有点大,我还真没有这个能力能把这个问题说清楚,就我个人而言,也许是从小养成的自学习惯,在学习中,有的时候有些优势,但也不能说这就是唯一的路。...
  • 全面的网站评估方案

    2020-09-22 16:21:55
    有时会被问到“看看XXX网站如何?”之类的问题。谈到评估,通常都是指产品级的网站,如果模式很新,了解需要花一定时间。于是,很多人又问“那么你仅从UI/UE的角度看看呢?”首先我们达成共识,一切花里胡哨都在为...
  • 开展全面的网站评估

    2016-06-20 19:13:00
    有时会被问到“看看XXX网站如何?”之类的问题。 谈到评估,通常都是指产品级的网站,如果模式很新,了解需要花一定时间。于是,很多人又问“那么你仅从UI/UE的角度看看呢?”首先我们达成共识,一切花里胡哨都在...
  • 只有善于学习,才能站更高、看的更远、想的更深的看问题、想问题、发现问题、分析问题。因此,要当好一名能干事、会干事、干好事的秘书,必须努力成为学习型秘书。只有努力成为学习型秘书,才能更好的为全面建设的...
  • 如何炒股

    2007-05-15 22:54:00
    投资者要正确研判行情,关键是要跳出自我的小圈子,站在所有投资大众的立场角度上看问题。要做到这一点,一方面要站得高,看得远;另一方面要主动将自己的角色进行置换,以期从更加客观的角度思考市场走势的未来趋向...
  • 一起来看看如何制定一个学习计划! 一、进行自我分析 我们每天都在学习,可能有的同学没有想过我是怎样学习的这个问题,因此制订计划前首先进行自我分析。 分析自己的学习特点 可以仔细回顾一下自己的学习情况,...
  • 如何制定学习计划.doc

    2021-01-14 22:01:52
    如何制定学习计划 一、进行自我分析 我们每天都在学习,可能有的同学没有想过我是怎样学习的这个问题,因此制订计划前首先进行自我分析。 1、分析自己的学习特点,同学们可以仔细回顾一下自己的学习情况,找出学习...
  • “六六想六教育”寒假实践报告 改革开放三十年来,我国广大农村发生了翻天覆地的变化,在绝大部分农民解决了温饱问题之后,农村的政治文明精神文明和物质文明都获得了空前的发展。这些成就的取得,是党领导广大...
  • SEO诊断也是一项针对客户做好的网站,从SEO技术策略的角度分析存在的问题,以及如何改进,如何使网站更符合搜索引擎的习惯,如何使用最少的外链的服务,用最少的时间和最少的钱快速提高网站的关键词排名。...
  • 看看学霸是如何制定学习计划表的。 学霸学习计划表 1. 进行自我分析 我们每天都在学习,可能有的同学没有想过我是怎样学习的这个问题,因此制订计划前首先进行自我分析。 分析自己的学习特点 同学们可以仔细...
  • 寒假学习计划如何制定 一份好的学习计划大致包括三方面的内容。 一、进行自我分析 我们每天都在学习,可能有的同学没有想过我是怎样学习的这个问题,因此制订计划前首先进行自我分析。 1、分析自己的学习特点,...
  • 我在初中的时候,语法基础打比较牢固,然后上高中,我在高三之前就完整的过一遍分章节的语法书,这样就会对语法有个全面完整的掌握。每天再背一些句型或者一些短语,因为这些东西除了可以用在作文里面,还可以...
  • 今天就给大家全面总结一下:Python如何打包成exe,以及如何足够小。 标准打包 目前比较常见的打包exe方法都是通过Pyinstaller来实现的,本文也将使用这种常规方法。如果对这块已经很熟悉的小伙伴,可以直接...
  • 作为一名已经在农村工作的大学生“村官”应该站在农村的角度来看问题,考虑的应该是农村的事务,打交道的是全体农民,这种角色的转换要求他们必须放下身份、用活知识、加强实践,要广泛地接触农民,了解农民的生活...
  • 如何选择软件代理商

    2010-06-26 15:40:00
    软件都一样,就是看如何选择上级(一定要): 1.很多代理在降价卖软件,其实是对你的不负责.他给你降价肯定也给其它人降价,而官方是禁止降价的,迟早会被封号.如果上级被封号了,谁再给你保证售后呢?本店从来...
  • 大学两年,塑造了一个健康,充满自信的我,自信来自实力,但同时也要认识到,眼下社会变革迅速,对人才的要求也越来越高,社会是在不断变化,发展的,要用发展的眼光看问题,自身还有很多的缺点和不足,要适应社会的发展,不断...
  • 简介:现代人离不开手机,更离不开Wi-Fi。很多同学经常吐槽家中Wi-Fi用不爽,打游戏视频又卡又慢...针对大家常见的问题,和坊间各种“谣传”,今天我们特别邀请了阿里工程师艺超,来为大家做全面的梳理分类,希...
  • 从我国秘书学建立至今的十来年,这一根本性问题也始终没能得到统一认识。*就几个相关问题谈谈自己的观点。 一、秘书应认定为是一种职务 这是针对学术界有人提到的秘书是一种职位、职业、职称而言的。把秘书界定在...
  • 重要的是要看看智能城市背后的驱动力以及个人数据如何与这些驱动力相吻合,以更全面地了解生活在智慧城市中的意义。 推动智能城市需求的基本因素以及如何将个人数据用作这些驱动因素的一部分如下: 世界人口增加...
  • 可能我问题描述很拗口,大家一下下面的需求例子便知: 21.循序渐进22.世俗23.间接经验与直接经验相结合24.教科书25.舒尔茨26.培养人27.人的全面发展28.皮亚杰29.德鲁克30.归宿31.民主平等32....
  • 刚刚担任项目经理的你要面对的第一件就是要明确自己在项目组中的位置...你不再是一个程序员,你需要全身心得关注软件开发过程中的每一个环节,要把自己考虑问题的角度变更加全面,从整个业务系统,乃至公司的角度去

空空如也

空空如也

1 2 3 4 5 ... 19
收藏数 380
精华内容 152
关键字:

如何看问题看得全面