RPC框架核心学习内容
线程池
1. 核心参数
corePoolSIze :核心池大小,未达到此参数会创建新的线程进行执行。达到此参数限制会放入等待队列中(小于maximunPoolSize)。
maximumPoolSize:最大能达到的数量限制,阻塞队列满且达到最大线程数的时候会根据抛弃策略进行丢弃。
keepAliveTime:当线程数大于核心时,多于的空闲线程最多存活时间。
workQueue:当线程舒服超过核心线程数的时候用于保存任务的队列。三种类型:无界队列、有界队列、同步移交。
threadFactory:执行程序创建新线程时使用的工厂。
rejectedExecutionHandler:拒绝策略。提供四种拒绝策略。
2. workQueue
1. 无界队列(linkedBlockingQueue)
其实并不能算无限,这个队列的默认大小是Integer.MAXVALUE。newFixedThreadPool会采用此种队列。当任务耗时较长的时候,会无限在队列中创建等待任务,堆积大量的请求。可能会溢出造成OOM。大量任务被添加到这个无界队列中,会导致cpu和内存飙升导致服务器挂掉。
2. 有界队列(ArrayBolckingQueue、PriorityBlockingQueue)
FIFO原则的 ArrayBolckingQueue 和优先级队列 PriorityBlockingQueue(优先级由任务的 Comparator 决定)。
线程池较小、有界队列较大时可减少内存消耗,降低cpu使用率和上下文切换,但是会限制系统吞吐量,可能会导致部分任务被丢失。
3. 同步移交队列(SynchronousQueue)
不是一种真正的队列,时一种线程间的移交机制。要将一个队列放入一种,必须要另一个线程正在等待接受这个元素。只有在使用无界线程池(newCachedThreadPool)或者由饱和策略的时候才建议使用该队列。
newCachedThreadPool 的概念就是需要一个线程接受才能使任务顺利进入队列,否则的话就需要新启一个线程(刚开始的时候也就是会新创建线程后才会开始进行处理)。最大线程大小是Integer.MAXVALUE。任务太多时会创建大量的线程,可能会造成OOM。
所以阿里的规范里面不建议使用Executor,建议使用ThreadPoolExecutor自己创建。
3. 拒绝策略
1. AbortPolicy 中止策略
默认饱和策略。饱和时会抛出 RejectedExecutionException(RuntimeException),可捕获异常处理。
2. DiscardPolicy 抛弃策略
不做任何处理,直接抛弃任务
3. DiscardOldestPolicy抛弃旧任务策略
抛弃最老任务。抛弃掉队列头部的元素,再尝试提交任务。
如果使用的是优先级队列会导致优先级最高的任务被抛弃,不建议配合使用。
4. CallerRunsPolicy 调用者运行
使用调用者的线程来运行此任务。运行此任务期间无法提交新的任务。
动态代理
1. JDK动态代理
使用反射进行创建,被代理类需实现 InvocationHandler 接口
Method method = serviceClass.