diff --git a/.idea/workspace.xml b/.idea/workspace.xml index 525574c..42daf74 100644 --- a/.idea/workspace.xml +++ b/.idea/workspace.xml @@ -1,7 +1,7 @@ - + @@ -265,8 +265,10 @@ - - + + + + 1581102125245 @@ -604,12 +606,12 @@ - - 1585657673868 + + 1585377224497 @@ -704,14 +706,14 @@ - + - - - + + + - + @@ -754,38 +756,34 @@ - + - + - - - - - + - + - + - + - + - + diff --git a/Rocket.md b/Rocket.md index 04c92ab..6c8ac81 100644 --- a/Rocket.md +++ b/Rocket.md @@ -409,12 +409,20 @@ AQS内部有3个对象,一个是state(用于计数器,类似gc的回收计 2. 一般来说,如果是IO密集型应用,则线程池大小设置为2N+1。 3. 在IO优化中,线程等待时间所占比例越高,需要越多线程,线程CPU时间所占比例越高,需要越少线程。这样的估算公式可能更适合:最佳线程数目 = ((线程等待时间+线程CPU时间)/线程CPU时间 )* CPU数目 +### 如何实现一个带优先级的线程池 + +利用priority参数,继承 ThreadPoolExecutor 使用 PriorityBlockingQueue 优先级队列。 + ### ThreadLocal的原理和实现 ThreadLoal 变量,线程局部变量,同一个 ThreadLocal 所包含的对象,在不同的 Thread 中有不同的副本。ThreadLocal 变量通常被private static修饰。当一个线程结束时,它所使用的所有 ThreadLocal 相对的实例副本都可被回收。 一个线程内可以存在多个 ThreadLocal 对象,所以其实是 ThreadLocal 内部维护了一个 Map ,这个 Map 不是直接使用的 HashMap ,而是 ThreadLocal 实现的一个叫做 ThreadLocalMap 的静态内部类。而我们使用的 get()、set() 方法其实都是调用了这个ThreadLocalMap类对应的 get()、set() 方法。 +### ThreadLocal中的内存泄漏 + +在ThreadLocal中内存泄漏是指ThreadLocalMap中的Entry中的key为null,而value不为null。因为key为null导致value一直访问不到,而根据可达性分析导致在垃圾回收的时候进行可达性分析的时候,value可达从而不会被回收掉,但是该value永远不能被访问到,这样就存在了内存泄漏。如果 key 是强引用,那么发生 GC 时 ThreadLocalMap 还持有 ThreadLocal 的强引用,会导致 ThreadLocal 不会被回收,从而导致内存泄漏。弱引用 ThreadLocal 不会内存泄漏,对应的 value 在下一次 ThreadLocalMap 调用 set、get、remove 方法时被清除,这算是最优的解决方案。 + ### ThreadLocal为什么要使用弱引用和内存泄露问题 Map中的key为一个threadlocal实例. 这个Map的确使用了弱引用,不过弱引用只是针对key.每个key都弱引用指向threadlocal.假如每个key都强引用指向threadlocal,也就是上图虚线那里是个强引用,那么这个threadlocal就会因为和entry存在强引用无法被回收!造成内存泄漏 ,除非线程结束,线程被回收了,map也跟着回收。 @@ -431,6 +439,11 @@ HashSet的value存的是一个static finial PRESENT = newObject()。而HashSet 未精确定义字节。Java语言表达式所操作的boolean值,在编译之后都使用Java虚拟机中的int数据类型来代替,而boolean数组将会被编码成Java虚拟机的byte数组,每个元素boolean元素占8位。 +### 阻塞非阻塞与同步异步的区别 + +1. 同步和异步关注的是消息通信机制,所谓同步,就是在发出一个调用时,在没有得到结果之前,该调用就不返回。但是一旦调用返回,就得到返回值了。而异步则是相反,调用在发出之后,这个调用就直接返回了,所以没有返回结果。换句话说,当一个异步过程调用发出后,调用者不会立刻得到结果。而是在调用发出后,被调用者通过状态、通知来通知调用者,或通过回调函数处理这个调用。 +2. 阻塞和非阻塞关注的是程序在等待调用结果(消息,返回值)时的状态。阻塞调用是指调用结果返回之前,当前线程会被挂起。调用线程只有在得到结果之后才会返回。非阻塞调用指在不能立刻得到结果之前,该调用不会阻塞当前线程。 + ## Spring ### 什么是三级缓存 @@ -691,7 +704,7 @@ void quick_sort(int a[], int low, int high){ ### 秒杀并发情况下库存为负数问题 1. for update显示加锁 -2. 把udpate语句写在前边,先把数量-1,之后select出库存如果>-1就commit,否则rollback。 +2. 把update语句写在前边,先把数量-1,之后select出库存如果>-1就commit,否则rollback。 ``` update products set quantity = quantity-1 WHERE id=3; select quantity from products WHERE id=3 for update;