1. 如果有几亿的数据在一张表中,需要操作的时候应该怎么处理
2.排序算法都有哪些,快速排序的思想
3.hashmap了解吗,什么时候初始化
4.java的并发包有什么了解吗
5.原子类有了解吗,原理是什么
6.CAS的好处和坏处是什么
7.jvm的内存模型,详细说一下jvm的堆空间划分
8.jvm的gc算法,为什么要gc?full gc和minor gc的区别?分别都是什么时候触发
答案如下:
1. 如果有几亿的数据在一张表中,需要操作的时候应该怎么处理
建立索引[基本不能解决问题,数据量已经很大了]
使用redis缓存,数据库主从分离
对于数据库表中的数据进行分库,分表,分区
分表可以将一张表进行水平拆分和垂直拆分,垂直拆分是根据业务进行拆分,将一张表根据业务进行拆分,水平拆分是把多条数据拆分,将一张表分为N页,并通过一个新页(总表)记录每个页的位置
分区是指把不常用的数据进行迁移到其他地方,这个需要定期维护
2.排序算法都有哪些,快速排序的思想
选择排序,插入排序,冒泡排序,快速排序,希尔排序,基数排序,归并排序,堆排序
快排的思想是分治
确定一个基准值,通过一趟排序将要排序的数据分割成独立的两部分,左边的数据比指定的值小,右边的数据比指定的值大,然后再对左右两边分别进行递归
快排代码:
#include void print(int a[],int n) { int i; for(i=0;i { printf("%d ",a[i]); } printf("\n"); } void QuickSort(int a[],int start,int end) { int i=start,j=end; //选中第一个的值为start int base=a[start]; int temp; //递归的结束条件,如果i>=j;说明数组已经排好序了,直接返回 if(i>=j) return ; while(i { //从后向前找出比基准值小的下标 [比基准值大就继续往前找] for(;j>i&&a[j]>=base;j--); //从前向后找出比基准值大的小标 [比基准值小就继续往后找] for(;i //交换找到的值 if(i { temp=a[i]; a[i]=a[j]; a[j]=temp; } //继续while循环 } //i 的值就是最后的位置,将其与基准值进行 a[start]=a[i]; a[i]=base; QuickSort(a,start,i-1); QuickSort(a,i+1,end); } int main(void) { int a[10]={3,5,7,6,1,-9,-8,79,100,0}; print(a,10); QuickSort(a,0,9); print(a,10); } |
Java代码实现
public class QuickSort { public static void main(String[] args) { int[] a = {3, 5, 7, 6, 1, -9, -8, 79, 100, 0}; print(a); QuickSort(a, 0, a.length - 1); print(a); }
public static void QuickSort(int[] a, int start, int end) { int i=start,j=end; int base=a[start]; int temp; if(i>=j) return; while (i { for(;j>i&&a[j]>=base;j--); for(;i if(i { temp=a[i]; a[i]=a[j]; a[j]=temp; } } a[start]=a[i]; a[i]=base; QuickSort(a,start,i-1); QuickSort(a,i+1,end); } public static void print(int[] a) { for (int i : a) { System.out.print(i); System.out.print(" "); } System.out.println(); } } |
3.hashmap了解吗,什么时候初始化
HashMap初始化的时间是在进行put操作的时候,调用resize方法
4.java的并发包有什么了解吗
https://www.cnblogs.com/cccw/p/5837448.html
Java.util.concurrent包
该包下面的类有
1.ConcurrentHashMap使用分段存储的方法
2.ReentrantLock底层使用volatile和AQS同步器进行实现
3.Condition接口,实现类例如ReentrantLock
4.ThreadPoolExcutor线程池
5.Future和FutureTask异步等待
6.CopyOnWriteArrayList底层实是ReentrantLock
5.原子类有了解吗,原理是什么
Atomic原子类
1. 原子类由CAS操作保持原子性,由volatile关键字保证可见性
2. 原子类可以粗略分为5类
a. 整型,长整型,布尔型,引用类型的原子类
AtomicInteger,AtomicLong,AtomicBoolean.AtomicReference
b. 整型数组,长整型数组,引用数组的原子类
AtomicIntegerArray,AtomicLongArrat,AtomicReferenceArray
c. 整型字段,长整型字段,引用字段更新的原子类
AtomicIntegerFieldUpdater,AtomicLongFieldUpdater,AtomicReferenceUpdater
d 解决ABA问题的原子类
AtomicMarkableReference,AtomicStampedReference
E jdk1.8新增的更高性能的原子累加器
LongAdder,DoubleAdder,LongAccumulator,DoubleAccumulator
6.CAS的好处和坏处是什么
好处:乐观锁,可以解决并发带来的不安全的问题
https://www.cnblogs.com/senlinyang/p/7875381.html
坏处:
1. ABA问题
线程1从内存位置V中取出A,这时候另一个线程2从内存中取出A并且线程2进行一些操作变成了B,然后线程2又将v位置的数据变成A,这时候线程1进行CAS操作发现内存中仍然是A,,然后线程1操作成功,尽管操作成功,但是仍然存在一些线程安全问题
比如A在栈顶,做了一些操作之后例如push一些数字,还把A放在栈顶,这时候就有可能增加一些东西,同时还可能减少一些东西
2. 循环开销时间大
自旋CAS(不成功就一直循环执行,直到成功)如果长时间不成功,那么会给cpu带来非常大的执行开销,如果jvm能支持处理的pause指令,那么效率会有一定的提升
Pause指令有两个作用:可以延迟流水线的执行指令,使得cpu不会消耗过多的执行资源,延迟的时间取决与具体实现的版本,第二可以避免退出循环的时候因为内存顺序冲突而引起的cpu流水线被清空
3只能保证一个共享变量的原子操作
当对多个锁进行操作时,CAS无法保证原子性,这个时候可以用锁,或者将两个两个变量合并成一个变量进行操作.比如有两个共享变量i=2,j=a,合并一下两个变量ij=2a,然后用cas来操作I,j,jdk提供了AtmoicReference类来保证引用对象之间的原子性
7.jvm的内存模型,详细说一下jvm的堆空间划分
内存模型:
JMM决定一个线程对共享变量的写吐何时对另一个线程可见。线程之间的共享内存在主内存中,每个线程还有一个私有的本地内存,本地内存中存储了用于读写的共享变量的副本
支撑java内存模型的基础原理
指令重排序
在执行程序时,编译器和cpu为了提高效率会对指令进行重排序,通过插入memory Barrier禁止重排序,为上一层提供可见性保证
Jvm堆的空间划分
https://blog.csdn.net/weixin_40160053/article/details/82841508
jdk1.8之前分为新生代老年代和永久代
jdk1.8之后将永久代分到栈中
新生代:所有new的对象都在堆里面,对象有限分配到Eden区,可以通过参数来指定Eden区和survivior的比例(复制算法中用到的,1:1空间划分太浪费)
老年代:大对象和长期存活的对象
永久代:包含元数据信息,如class,method的detail信息
New一个对象的过程:
8.jvm的gc算法,为什么要gc?full gc和minor gc的区别?分别都是什么时候触发
如果只创建对象,不回收对象,那么内存很快就会被耗尽,所以要进行GC
MinorGC触发条件,当新生代的Eden区满时,会触发minorGC
FullGC触发条件:
a system.gc系统执行GC,但是不是必然执行(没有其他对象对其进行引用时才确定)
b.老年代空间不足
c方法区空间不足
d minor gc之后进入老年代的平均大小大于老年代的可用内存
e由Eden区的from space区域向tospace区域转换时,tospace区域的内存不足,且把该对象转向老年代之后,老年代的可用内存小于该对象大小
(一)Minor GC
Minor GC 是发生在新生代中的垃圾收集动作,所采用的是复制算法。 是发生在新生代中的垃圾收集动作,所采用的是复制算法。
当对象在 在 Eden 区 区和 和 From Survivor 区 区, ,(Survivor 区“To” 是空的), ,在经过一次 在经过一次 Minor
GC 后,Eden 区中所有存活的对象都会被复制到 区中所有存活的对象都会被复制到“ “To” ” ,而在“ “From” ” 区中,仍存活的
对象会根据他们的年龄值来决定去向。对象在 对象会根据他们的年龄值来决定去向。对象在 Survivor 次 区每熬过一次 Minor GC,就将 ,就将
对象的年龄 对象的年龄 + 1时 ,当对象的年龄达到某个值时 ( 默认是 15 岁,可以通过参数 岁,可以通过参数-XX:MaxTenuringThreshold 定 来设定 )会被移动到年老代中 会被移动到年老代中 , 没有达到阈值的对象会被复制到“ “To” ” 区域 ,经过这次 经过这次 GC 后 后, ,Eden 区和 From 区已经被清空 区已经被清空 。 这个时候 ,“ “From” ”和“ “To” ” 会交换他们的角色 , 也就是新的“ “To” ”就是上次 就是上次 GC 前的 前的“ “From” ” , 新的“ “From” ”就是上次 就是上次 GC 前的 前的“ “To” 不管怎样, ,都会保证名为 都会保证名为 To 的 的 Survivor 区域是空的 区域是空的Minor GC会一直重复这样的过程,直到“ “To” ” 区被填满,“ “To” ” 区被填满之后,会将所有对象移动到年老代中。
(二)Full GC
Full GC 是 是 发生在老年代 的垃圾收集动作,所采用的是标记 标记-清除 清除或标记 或标记-整理 整理 算法 。
在 老年代里面的对象几乎都是在 Survivor , 区域中熬过来的, Full GC 发生的次数不
有 会有 Minor GC 次 那么频繁,并且做一次 Full GC 次 要比进行一次 Minor GC 的时间更长。
另外, , 标记- 清除算法收集垃圾的时候会产生许多的内存碎片 ( 间 即不连续的内存空间 )此后需要为较大的对象分配内存空间时,若无法找到足够的连续的内存空间,就会提前触发一次GC的收集动作。