Golang Channel
Go 1.9 Sync Map
基于Go 1.9 解析Sync Map
cs-interview
Java部分
- java比较 icompare
- tomcat 热部署 加载方式与双亲委派模型?
- java io api 过滤器模式?
- threadLocal 实现原理?
- tcp ip协议
- 服务端如何确定seesion是同一个?
- 内存屏障(Memory Barriers)
- lock synchronized ReentrantLock
- jvm JVM的年轻代分为哪几代?年轻代什么时候会进入老年代?
- jvm JVM 垃圾回收算法?(注意年轻代与老年代是不一样的)?
- jvm内存模型 一个变量初始化 怎么分配内存 分配到什么地方?
- 不使用双亲委派模型的缺点?
- java 开源序列化框架有哪些?彼此之间有什么区别(优缺点)?
- java.util.concurrent hashmap 相关问题
- JAVA线程sleep和wait方法区别
https://jiankunking.blog.csdn.net/article/details/79824353 - PriorityQueue(优先级队列) 堆相关问题
- 常见的负载均衡算法
- java 阻塞队列 相关问题,阻塞具体是如何实现的?
- 静态代码块. 构造代码块. 构造函数以及Java类初始化顺序
- java 枚举的实现,内部如何进行存储的?
- 静态内部类与普通内部类,在用法. 初始化方面的区别?
- java 原子性 可见性 顺序性是通过什么来保证的?
- java 多线程内共享的模型
- 阻塞非阻塞与同步异步
- java nio原理
- 读写锁 自旋锁 尝试锁(cas) cas如何保证,查询到修改这个过程是原子的?
- 一个类中的静态变量是在类加载的哪个步骤加载的?
- synchronized与ReentrantLock 实现原理区别?
- threadlocal 实现原理?应用场景?
- 常见的设计模式
- 分布式事务
- 线程池工作原理及机制
- 线程挂了 保活
- keepalive 保活策略?
- Protocol Buffers 适用场景?
- http tcp 相比多了些什么?有什么不一样的地方?
- http与https区别?加密算法是?
- wait 是释放锁?为什么释放了锁,线程就挂起了。为什么线程wait了就挂起了?
- CMS 垃圾回收
- hashmap 线程不安全 什么时候会出现?会出现什么问题?(hashmap为啥线程不安全?)
- equals 比较原理?
- jvm 内存分布
- arraylist linklist
- interger 为null 转int 会发生什么?
- hashmap与hashset的关系?
- 线程与协程的区别?协程的优势?
- JDK8 如何实现协程?
- java lambda 实现原理
- java stream 实现原理
- 永久代(permanent generation)与Metaspace
- 如何保证GC ROOTS找的全?(比如中G1中)
- G1清理老年代. 年轻代是遍历所有吗?
- 可重入锁和不可重入锁?不可重入锁有啥缺陷?
- CPU密集型 Java线程池大小为何会大多被设置成CPU核心数+1?
- 什么情况下会出现ClassNotFoundException?
- 线程有几种状态?
- 如何动态上报JVM信息,以便后期排查OOM等问题?
- ConcurrentHashMap put的时候加锁的是数组上的元素 还是啥?
- Concurrenthashmap中用到的优化技巧?
- LRU如何实现?
- 为什么Concurrenthashmap扩容是安全的?
- LinkedHashMap和HashMap 区别?
- CompletableFuture get(long timeout, TimeUnit unit) throws TimeoutException, ExecutionException实现
https://medium.com/@sergeykuptsov/how-it-works-in-java-completablefuture-3031dbbca66d
64、Java time-based map/cache with expiring keys
https://stackoverflow.com/questions/3802370/java-time-based-map-cache-with-expiring-keys
65、jmap 其实是多个线程 他们之间是怎么通信 dump出数据的?(jmap命令的实现原理)
66、GC的年轻代Survivor区,为什么是2个,而不是1个?
https://stackoverflow.com/questions/10695298/java-gc-why-two-survivor-regions
简单来说2个Survivor区,就是整理内存碎片的时候方便。
67、类加载器及类加载机制
MySQL部分
- mysql 时间 比较无效 原因?
- mysql 数据库 索引 是以什么数据结构形式存储的?
- mysql与sql server 异同点? 原理上?
- 索引顺序对于索引效果的影响?
- 数据库索引如何优化(从哪几个方面)?
- mysql优化有哪些?
- 比如一个表中有100条数据,a字段的值,是从1到100,我要更新其中的数据,where条件时a>10
mysql通过innodb引擎的话,是通过表锁还是行锁? - mysql mvcc多版本并发控制
- mysql为什么选中B+ TREE而不是B TREE?两种数据结构有什么区别?
B+ 树继承于 B 树,都限定了节点中数据数目和子节点的数目。B 树所有节点都可以映射数据,B+ 树只有叶子节点可以映射数据。
单独看这部分设计,看不出 B+ 树的优势。为了只有叶子节点可以映射数据,B+ 树创造了很多冗余的索引(所有非叶子节点都是冗余索引),这些冗余索引让 B+ 树在插入、删除的效率都更高,而且可以自动平衡,因此 B+ 树的所有叶子节点总是在一个层级上。所以 B+ 树可以用一条链表串联所有的叶子节点,也就是索引数据,这让 B+ 树的范围查找和聚合运算更快。
- mysql 范围查询?索引的数据结构是如何处理的?
- mysql事务提交原理?
- 聚集索引 非聚集索引 查询效率?
- mysql 乐观锁 悲观锁
- 数据库分库分表
基础
- 进程间通信方式有哪些?
- 有些信号你能捕获,有些信号你是捕获不了的,捕获不了的信号有哪些?
- zookeeper 可以通过watch,用来做进程间通信,那么zk底层是使用什么方式来实现进程间通信的?依赖操作系统如何实现的?
- socket通信
- keepalive时间限制
- tcp 如何处理粘包问题
- http协议 如何区分header头还有body体
- tcp 协议网络段 协议簇
- 一次完整的http请求
- http code 302 304含义
线上
- 如何线上debug?比如线上的cpu爆了,这个步骤是?
- 线上fd耗光了,如何排查?
- 如何定位OOM 问题?
Kakfa
- kafka某个broker上是否可以有无限个topic?或者万级别的topic?
- kafka 设计,还有broker上文件存储
- kakfa是否支持顺序消费消息?
- zk在kafka集群中的作用
- kafka 消费时候可以批量拉取?
- 消息队列 选型 为什么选择kafka?
- kafka增加. 删除节点时如何迁移数据?新的数据如何分配?
- kafka写入消息 如何保证回滚或者保证不被消费
- kafka 如何确保消息消费且只消费一次?
- kafka 大批量写入 是怎么传输的?
对象缓存池
https://www.sohu.com/a/346950666_100123073
https://github.com/a0x8o/kafka/blob/master/clients/src/main/java/org/apache/kafka/clients/producer/internals/BufferPool.java - Kafka和RocketMQ存储区别
https://www.cnblogs.com/lewis09/p/11168902.html
ElasticSearch
- 在ElasticSearch中,集群(Cluster),节点(Node),分片(Shard),Indices(索引),replicas(备份)之间是什么关系?
- elasticsearch整个建索引. 查询的过程
- elasticsearch如何选举
- ik 是如何进行分词的?
- es Scroll 原理? Search After原理?
- es 副本作用?
- mysql elasticsearch 查询对比?(比如整个搜索流程)
- elasticsearch match filter 差异点?
- es 评分机制/原理
OpenTSDB
- OpenTSDB与HBase 关系
脑经急转弯
- 判断一个整数是2的N次方?
- 二叉树拷贝(非递归)
- BitMap算法(应用)
其他
- 分布式锁有哪些实现方式?
- 分布式事务
- 异地多活
- zookeeper集群 当一个节点挂了一天,当再次启动的时候,如何识别哪个是leader?
- 有什么知名的开源apm(Application Performance Management)工具吗?
- pinpoint 原理?
- consul template作用?如何与prometheus交互的?
金融
- 同业拆借
- 信用卡消费一笔钱,是如何到收款人的账户的?(整个流转过程)
- 复式记账
Spring
- spring 注入 接口即如何注入一个接口的多个实现类?
- spring 中用到的设计模式?spring中一次完整的http请求链路?
- 手写stater
- spring 类自动加载机制
- spring fegin 接口相互调用异常问题解决,有没有熔断啥的配置?
关于Spring AOP与IOC的个人思考
在阅读本文前,强烈建议阅读:
Java JDK 动态代理(AOP)使用及实现原理分析
Java HashMap
代码基于 Jdk1.8
Java-JDK-动态代理(AOP)使用及实现原理分析
一、什么是代理?
代理是一种常用的设计模式,其目的就是为其他对象提供一个代理以控制对某个对象的访问。代理类负责为委托类预处理消息,过滤消息并转发消息,以及进行消息被委托类执行后的后续处理。
代理模式UML图:
简单结构示意图:
为了保持行为的一致性,代理类和委托类通常会实现相同的接口,所以在访问者看来两者没有丝毫的区别。通过代理类这中间一层,能有效控制对委托类对象的直接访问,也可以很好地隐藏和保护委托类对象,同时也为实施不同控制策略预留了空间,从而在设计上获得了更大的灵活性。Java 动态代理机制以巧妙的方式近乎完美地实践了代理模式的设计理念。
二、Java 动态代理类
Java动态代理类位于java.lang.reflect包下,一般主要涉及到以下两个类:
(1)Interface InvocationHandler:该接口中仅定义了一个方法
1 | public object invoke(Object obj,Method method, Object[] args) |
在实际使用时,第一个参数obj一般是指代理类,method是被代理的方法,如上例中的request(),args为该方法的参数数组。这个抽象方法在代理类中动态实现。
(2)Proxy:该类即为动态代理类,其中主要包含以下内容:
protected Proxy(InvocationHandler h):构造函数,用于给内部的h赋值。
static Class getProxyClass(
ClassLoader loader,
Class[] interfaces):获得一个代理类,其中loader是类装载器,interfaces是真实类所拥有的全部接口的数组。
static Object newProxyInstance(ClassLoaderloader, Class[] interfaces,InvocationHandler h):返回代理类的一个实例,返回后的代理类可以当作被代理类使用(可使用被代理类的在Subject接口中声明过的方法)
所谓DynamicProxy是这样一种class:它是在运行时生成的class,在生成它时你必须提供一组interface给它,然后该class就宣称它实现了这些interface。你当然可以把该class的实例当作这些interface中的任何一个来用。当然,这个DynamicProxy其实就是一个Proxy,它不会替你作实质性的工作,在生成它的实例时你必须提供一个handler,由它接管实际的工作。
在使用动态代理类时,我们必须实现InvocationHandler接口
通过这种方式,被代理的对象(RealSubject)可以在运行时动态改变,需要控制的接口(Subject接口)可以在运行时改变,控制的方式(DynamicSubject类)也可以动态改变,从而实现了非常灵活的动态代理关系。
动态代理步骤:
-
创建一个实现接口InvocationHandler的类,它必须实现invoke方法
-
创建被代理的类以及接口
-
通过Proxy的静态方法
newProxyInstance(ClassLoaderloader,Class[]interfaces,InvocationHandler h)创建一个代理
- 通过代理调用方法
三、JDK的动态代理怎么使用?
1、需要动态代理的接口:
1 | package jiankunking; |
2、需要代理的实际对象
1 |
|
3、调用处理器实现类(有木有感觉这里就是传说中的AOP啊)
1 | package jiankunking; |
4、测试
1 | package jiankunking; |
5、输出结果如下:
四、动态代理怎么实现的?
从使用代码中可以看出,关键点在:
1 | Subject subject = (Subject) Proxy.newProxyInstance(loader, interfaces, handler); |
通过跟踪提示代码可以看出:当代理对象调用真实对象的方法时,其会自动的跳转到代理对象关联的handler对象的invoke方法来进行调用。
也就是说,当代码执行到:subject.SayHello(“jiankunking”)这句话时,会自动调用InvocationHandlerImpl的invoke方法。这是为啥呢?
下面是代码跟分析的过程,不想看的朋友可以直接看结论
以下代码来自:JDK1.8.0_92
既然生成代理对象是用的Proxy类的静态方newProxyInstance,那么我们就去它的源码里看一下它到底都做了些什么?
1 | /** |
我们再进去getProxyClass0方法看一下:
1 | /** |
真相还是没有来到,继续,看一下 proxyClassCache
1 | /** |
奥,原来用了一下缓存啊
那么它对应的get方法啥样呢?
1 | /** |
我们可以看到它调用了 supplier.get(); 获取动态代理类,其中supplier是Factory,这个类定义在WeakCach的内部。
来瞅瞅,get里面又做了什么?
1 | public synchronized V get() { // serialize access |
发现重点还是木有出现,但我们可以看到它调用了valueFactory.apply(key, parameter)方法:
1 | /** |
通过看代码终于找到了重点:
1 | //生成字节码 |
那么接下来我们也使用测试一下,使用这个方法生成的字节码是个什么样子:
1 | package jiankunking; |
可以看一下这里代理对象的类型:
我们用jd-jui 工具将生成的字节码反编译:
1 | import java.lang.reflect.InvocationHandler; |
这就是最终真正的代理类,它继承自Proxy并实现了我们定义的Subject接口,也就是说:
1 | Subject subject = (Subject) Proxy.newProxyInstance(loader, interfaces, handler); |
这里的subject实际是这个类的一个实例,那么我们调用它的:
1 | public final String SayHello(String paramString) |
就是调用我们定义的InvocationHandlerImpl的 invoke方法:
上面是代码跟分析的过程,不想看的朋友可以直接看结论
五、结论
到了这里,终于解答了:
subject.SayHello(“jiankunking”)这句话时,为什么会自动调用InvocationHandlerImpl的invoke方法?
因为JDK生成的最终真正的代理类,它继承自Proxy并实现了我们定义的Subject接口,在实现Subject接口方法的内部,通过反射调用了InvocationHandlerImpl的invoke方法。
通过分析代码可以看出Java 动态代理,具体有如下四步骤:
-
通过实现 InvocationHandler 接口创建自己的调用处理器;
-
通过为 Proxy 类指定 ClassLoader 对象和一组 interface 来创建动态代理类;
-
通过反射机制获得动态代理类的构造函数,其唯一参数类型是调用处理器接口类型;
-
通过构造函数创建动态代理类实例,构造时调用处理器对象作为参数被传入。
通过IL分析C#中的委托、事件、Func、Action、Predicate之间的区别与联系
一直以来都是对于事件与委托比较混淆,而且不太会用。找了个时间,总结了一下,感觉清晰了很多。
先说一下个人理解的结论吧:
delegate是C#中的一种类型,它实际上是一个能够持有对某个方法的引用的类。
delegate声明的变量与delegate声明的事件,并没有本质的区别,事件是在delegate声明变量的基础上包装而成的,类似于变量与属性的关系(在IL代码中可以看到每一个delegate声明的事件都对应是私有的delegate声明的变量),提升了安全性。
Action 与Func:这两个其实说白了就是系统定义好的Delegate,他有很多重载的方法,便于各种应用情况下的调用。他在系统的System命名空间下,因此全局可见。
首先了解一下, ILDasm中图标含义:
该图来自:http://www.cnblogs.com/zery/p/3366175.html
委托创建步骤:
- 用delegate关键字创建一个委托,包括声明返回值和参数类型。
- 使用的地方接收这个委托。
- 创建这个委托的实例并指定一个返回值和参数类型匹配的方法传递过去。
一、事件与委托
新建一个事件委托测试项目:EventDelegateTest。
具体代码如下:
1 | namespace EventDelegateTest |
编译代码后,使用 Visual Studio 2010自带的ILDASM.EXE:
打开该dll,可以看到如下信息:
从上图可以看出如下几点信息:
1、delegate
委托 public delegate int delegateAction();在IL中是以类(delegateAction)的形式存在的
.NET将委托定义为一个密封类,派生自基类System.MulticastDelegate,并继承了基类的三个方法:
2、event
public event delegateAction OnActionEvent;在IL中不仅仅对应event OnActionEvent而且还对应一个field OnActionEvent;而field OnActionEvent与 public delegateAction daNew生成的field daNew是一样的.
都是以字段(field )的形式存在的。
双击event OnActionEvent可以看到如下信息:
在IL中事件被封装成了包含一个add_前缀和一个remove_前缀的的代码段。
其中,add_前缀的方法其实是通过调用Delegate.Combine()方法来实现的,组成了一个多播委托;remove_就是调用Delegate.Remove()方法,用于移除多播委托中的某个委托。
也就是说:事件其实就是一个特殊的多播委托。
那么对于事件进行这一次封装有什么好处呢?
1、因为delegate可以支持的操作非常多,比如我们可以写onXXXChanged += aaaFunc,把某个函数指针挂载到这个委托上面,但是我们也可以简单粗暴地直接写onXXXChanged = aaaFunc,让这个委托只包含这一个函数指针。不过这样一来会产生一个安全问题:如果我们用onXXXChanged = aaaFunc这样的写法,那么会把这个委托已拥有的其他函数指针给覆盖掉,这大概不是定义onXXXChanged的程序员想要看到的结果。
小注:虽然事件不能直接=某个函数,也不可以直接=null
2、还有一个问题就是onXXXChanged这个委托应该什么时候触发(即调用它所包含的函数指针)。从面向对象的角度来说,XXX改变了这个事实(即onXXXChaned的字面含义)应该由包含它的那个对象来决定。但实际上我们可以从这个对象的外部环境调用onXXXChanged,这既产生了安全问题也不符合面向对象的初衷。
说到这里对于事件与委托的管理算是说明白了,那么平时常用的Action与Func,与委托又有什么关系呢?
二、Action 与Func
Action 委托:封装一个方法,该方法具有参数(0到16个参数)并且不返回值。
具体形式如下:https://msdn.microsoft.com/zh-cn/library/system.action(v=vs.110).aspx
Func<T, TResult> 委托:封装一个具有参数(0到16个参数)并返回 TResult 参数指定的类型值的方法。
具体形式如下:https://msdn.microsoft.com/zh-cn/library/bb534960(v=vs.110).aspx
那么这Action与Func是怎么实现的呢?
1、Action(以Action<T1, T2> 委托:封装一个方法,该方法具有两个参数并且不返回值为例)
从微软公布的源码中,可以看到,如下实现:
1 | public Action<bool,bool> ac; |
上面这个声明就是:该方法具有两个参数并且不返回值的委托。
其余使用方式与委托变量一样。
2、Func(以Func<T1, T2, TResult> 委托:封装一个具有两个参数并返回 TResult 参数指定的类型值的方法为例)
从微软公布的源码中,可以看到,如下实现:
此处,可以看出Func与Action是类似的,唯一的区别就是,Func必须指定返回值的类型,使用方式与委托咱们自己使用委托变量是一样的,直接使用相应参数的Func或者Action声明变量,=或者+=挂载函数(方法即可)
这两个其实说白了就是系统定义好的Delegate,他有很多重载的方法,便于各种应用情况下的调用。他在系统的System命名空间下,因此全局可见。
三、Predicate
是返回bool型的泛型委托,Predicate有且只有一个参数,返回值固定为bool。表示定义一组条件并确定指定对象是否符合这些条件的方法。
此方法常在集合(Array 和 List
具体用法demo如下:
1 | using System; |
上例中说明了Predicate的使用,FindAll方法中,参数2即是一个Predicate,在具体的执行中,每一个数组的元素都会执行指定的方法,如果满足要求返回true,并会被存放在结果集中,不符合的则被剔除,最终返回的集合,即是结果判断后想要的集合。
Array.FindAll 泛型方法:
https://docs.microsoft.com/zh-cn/dotnet/api/system.array.findall?redirectedfrom=MSDN&view=netframework-4.8#System_Array_FindAll__1___0___System_Predicate___0__
以上代码执行结果为:
那么Predicate
从微软源码中可以看出Predicate
四、资料
参考文章:
http://www.zhihu.com/question/28932542
关于事件部分应用注意可以参考:
http://www.cnblogs.com/buptzym/archive/2013/03/15/2962300.html
.NET Framework 源码:
https://referencesource.microsoft.com
Delegate 类:
https://docs.microsoft.com/zh-cn/dotnet/api/system.delegate?redirectedfrom=MSDN&view=netframework-4.8