面试阿里P7挂了

前后折腾了1个月。面试内推蚂蚁金服AndroidP7。
先吐槽下,流程实在太长了,长到难以理解。
一面到二面中间等了2周多。还是我催内推的人帮我才约的二面。

一面电面,通过
二面电面,挂了

基本围绕做过的项目问问题。
总体来说给人还是挺舒服的感觉。

最后得出深度不够和学习主动性不够。

以此反思反思。

1.以往的工作经历经验最好能记录下来。
像我回答过程中好多东西都不太记得只剩下大概映像。比如HTTPS,客户端要放证书吗,到底是证书还是公钥?面试官跟我纠结了半天。说实话我真记不太清。
2.其次说话还是要讲究技巧。
程序员说话能力还是要提高。反正我自己感觉,我的回答好几个地方都没以更好的方式去回答。
比如问我你怎么会去看这个技术?
a回答:老大叫我去的。b回答:我自己想到的。效果肯定不一样。
3.真的还是要在某一方面特别牛逼,然后将问题引到这个方面上。HTTPS就是个例子,我记不清了,掉到面试官的坑里被他延展开来问。

还好已经有一家公司成功拿到OFFER。对于我来说还算幸运(面试了5 6家就这一个OFFER,也是惨不忍睹)。
这下阿里挂了可以静下心来去这家了。
说到底还是自己各个方面不够好,以后还是得努力学习啊!

AIDL中in out inout的区别

in out inout概念

去面试被问到这个问题(-_-!!)一会想不起来了。
其实这个问题呢挺简单,就是个概念问题。
网上呢千篇一律一句话,要从字面上理解还真不是一件容易的事(比如很多都是照着文档翻译“空对象”,怎么理解?其实是重新new了一个新的对象,并不是null)。

基本数据类型的修饰符都是in
in – 只能在客户端设置值,在服务端获取值,反之不可以。
out – 只能在服务端设置值,客户端获得服务端设置的值,如果客户端在传值给服务端时设置了初始值,服务端无法得到该值。
inout — 客户端和服务端之间形成双向的数据通路,客户端设置的值服务端可以获得,反之,服务端设置的值客户端也可以获得。

跨进程通信

AIDL的本质其实是跨进程,那么跨进程通信的话就需要对数据进行拷贝传输。
打个比方,AB两人在视频。
A在纸上写个"你好",其实是视频数据经过传输拷贝了一份到B的屏幕,然后显示出"你好"。可以说此"你好"非彼"你好",只是看上去一样而已。

再回到AIDL举个例子

in - A发送了"你好"到B,B收到后把"你好"改成了"你不好",但是B却没告诉A。所以A不知道B做了修改。
out - A发送了"你好"到B,B呢收到后压根没看,直接把"你好"丢了,然后又自己写了个"你不好"发送给A。A就看到了"你不好"。
inout - 就是A发送"你好"到B,B看到了"你好"并且改成"你不好"又发送给A,A就看到了"你不好"。

关于源码解析

简书上有个哥们从代码层面做了详细的解析写的挺好可以参考。
你真的理解AIDL中的in,out,inout么?

三、多线程的优缺点

前两篇大概讲了什么是多线程、多进程,还有并发与并行。
这篇就讲讲引入了多线程后的优点与缺点。

优点

更好的资源利用率

举个恶心的例子吧:
只有一个茅坑(单核),大家排队拉屎。

单线程

第一个人便秘(IO阻塞等),在里面死不出来,过了半小时终于要拉了(IO就绪等),然后出来了换后面的人。
就这样直到拉完估计得好几个小时(估计最后面的人都等的憋死了。。)。

单核多线程

第一个人便秘(IO阻塞等),在里面死不出来,这时后面说:“快滚,等你要拉的时候(IO就绪等)再来”。
好第一个人出来了,第二个人就进去拉。第二个人拉一半也便秘(IO阻塞等)了,这时换第三个人。
就这样直到都拉完,估计要不了半小时。
这样子茅坑(单核)的利用率是不是就提高了。

多核多线程

厕所扩建了,两个茅坑(双核),这样效率更高了。

更快的程序响应

咳,再举拉屎估计得吐了。
直接在编程上举例子吧:
QQ都用过,QQ发消息更都用过,字打完了点发送更不用说了。

单线程

点发送。一系列不属于界面的逻辑(底层会进行封包、socket发送、等待服务器回复),因此界面就卡住了鼠标也不能动了。然后就等吧。直到服务器回复OK了,才能继续打字点下一次发送。
这样叫你撩个妹,黄花菜都凉了。

单核多线程

点发送。一系列不属于界面的逻辑(底层会进行封包、socket发送、等待服务器回复)放在另外的线程,因此一会执行发送逻辑,一会执行界面,这个速度非常快,毫秒级的切换,因此界面就能动了,鼠标也能动了(其实中间也会卡只是卡几毫秒,人就感知不出来了)。就可以不等待服务器回复继续发下面的消息。
这样是不是界面上的响应速度就更快了呢?

多核多线程

这个更快了。界面归一个CPU,底层逻辑归一个CPU。撩妹效率简直成倍提升啊。

缺点

这么大的好处,总有缺点吧!

程序更复杂

比如从两个文件里读取字符串然后拼接输出。

从前

从开始到结束,顺着写下来就可以了。

open file
string content = read file
close file

open file2
string content2 = read file2
close file2

print content + content2

现在

要先创建线程,然后还得判断线程执行完没,最后才能拼接。(后面还会讲的资源问题,会更加增加代码复杂度)

thread {
    open file
    string content = read file
    close file
}
thread2 {
    open file2
    string content2 = read file2
    close file2
}
wait thread1
wait thread2
print content + content2

增加资源消耗

单线程

上个厕所井井有条,大家都不用抢。

多线程

这下好了,以前是在厕所外面站着等就好了,现在拉一半被赶出来还得提着裤子在厕所里等。
这不额外消耗了能量提裤子,占用厕所里有限的空间,而且几个人还得轮流换着用茅坑好几次,又消耗了更多的时间。
人太多了厕所就挤爆了(OOM)。

回到程序中来讲,就是多线程来回切换,需要将之前的状态保存到某个位置,当执行的时候又要将保存的状态恢复。这无疑带来了附加的资源消耗。虽然微乎其微,但是当你有1000个线程的时候就挺恐怖了。
所以说线程并不是越多越好。这也变相的增加了设计程序时多线程使用的复杂度。

总结

前面说了优缺点,当然缺点并不可怕,只要适当的使用多线程,对程序来说有质的飞跃。那么这个缺点就可以忽略不计了。

二、并发与并行

我们常说高并发,那高我们理解,就是非常多、大量的。那么并发呢?

并行

说并发前先说说并行,与并发一字之差。什么是并行呢?
说白了就是同一时刻干多个事情。这在单核CPU上是完全不可能的,你想你能同时吃饭和洗澡吗?
但是多核CPU的优势就体现了,每个核在同一时间点各干各的,你吃你的饭,我洗我的澡。

并发

再来说并发。能够在一定时间内处理多个任务就叫做并发。比如淘宝一秒钟能处理10万个订单。
你也可以一秒内先吃一口饭,再吃一口菜。
这在单核CPU上也是能够实现的,CPU分时间片执行。

总结

我们可以看出,最先其实是想解决并行问题,然而一个CPU搞不定啊,退而求其次使用并发来模拟。
再后来双核出现,并行也就能实现了。
并发的定义可以认为是并行定义的一个子集,一种特殊情况。
还是引用一个例子(网上找的^_^):

你吃饭吃到一半,电话来了,你一直到吃完了以后才去接,这就说明你不支持并发也不支持并行。
你吃饭吃到一半,电话来了,你停了下来接了电话,接完后继续吃饭,这说明你支持并发。
你吃饭吃到一半,电话来了,你一边打电话一边吃饭,这说明你支持并行。

一、多线程

说到多线程,是一个老生常谈的问题了。
那么什么是多线程呢?
后面将以java为开发语言为您娓娓道来。

多进程

在过去的单CPU的时代,同一时间CPU只能执行一个进程。后来在用户体验上并不太好,因为必须等到一个进程完成了,才能开始下一个进程。后来就发展出了多进程。CPU还是那个CPU,但是CPU可以一会做这个进程一会做那个进程,给人感觉好像同时在做多件事一样。
这样的话其实就有了极端情况:
1.举个例子:以前是坐在那等饭蒸熟再做其他事,现在是在等的时候先去做其他事。这个例子中效率显而易见。
2.再举个例子:护士(CPU)照看多个病房(进程),那么护士就得在多个病房之前跑来跑去。护士跑来跑去每次得记录之前的房间号,这样其实消耗了更多资源与时间(其实也很难察觉)。

但多进程总体来说给人感觉还是更快了。

多线程

再到后来,多进程貌似也满足不了需求,因为一个应用程序一个进程,那么在这个进程中还是串行,并且进程间资源的切换需要做很多处理,体验还是不那么好,就发展出了更轻量级的线程,可以认为多线程就是多进程的缩影,但是多线程使用的资源是进程所拥有的资源,因此各个线程间能够同时使用进程的资源。
再后来多核出现,就可以真正意义上的实现同一时间执行不同操作,至此真正的多进程多线程得以实现(是一个人搬砖快呢还是几个人一起搬砖快呢?)。
再看前面护士的例子:一个病房(进程)里有很多病人,但是护士(线程)在一个病房里不需要记录房间号就能查看每个病人的信息,因为病人信息都记录在房间的本子上(进程拥有的内存,病人共享内存)。然后还能再聘请一个护士(多线程),这样效率更高。

这个例子想了好久,感觉还是不太恰当,希望能集思广益。

协程

这个其实也是类似思想,但是粒度更细,更加轻量级,可以认为是线程中的线程,只是执行中断跳转到其他子程序的操作是由程序自己模拟的,这样就会在单线程环境中模拟多线程效果,就可以不用加锁,这样效率更高。
但遗憾的是java本身是不支持的。需要第三方库支持。