java面试一些问题汇总
1.cap理论:
一致,可用,分区容错
2.web2.0:
以分享为特征的实时网络,用户在互联网上拥有自己的数据,并且在不同的网站上使用
3.分布式事务:
事务:原子,一致,隔离,持久
# 开启事务
begin transaction update Account set balance = balance - money where id = 'A';
update Account set balance = balance + money where id = 'B'
# 提交事务
commit transaction Exception # 回滚事务rollback transaction
脏读:事务二读取到事务一中已经更新但是还没有提交的数据,这就是脏读。
不可重复读:一个事务两次读取同一个行数据结果不同,因为有其它的事务对数据进行了更新。此时的数据即为不可重复读数据。
幻读:同一事务执行两次查询,结果不一致,因为中间有其它的事务对数据进行更改。
事务隔离级别
读未提交(read uncommitted):最低级别,可能会导入脏读。
读已提交(read committed):可以避免脏读,只能查询到已经提交的数据。且具有良好的性能,但是不能避免不可重复读和幻读。
可重复读(repeatable):解决了不可重复读,可能会出现幻读。
串行化(serializable):通过加锁,使同一时间只能执行一个事务,不出现上述问题,但是可能会导致大量的超时现象和锁竞争。
分布式事务解决方案:
1.补偿事务TCC:针对每个操作,都要注册一个与其对应的确认和补偿(撤销)操作。它分为三个阶段:
- 首先在 Try 阶段,要先调用远程接口把 Smith 和 Bob 的钱给冻结起来。
- 在 Confirm 阶段,执行远程调用的转账的操作,转账成功进行解冻。
- 如果第2步执行成功,那么转账成功,如果第二步执行失败,则调用远程冻结接口对应的解冻方法 (Cancel)。
2.两阶段提交 2pc
3.本地消息表
4.mq事务消息
4.jvm:
1.堆,
Eden ——》s0 《——》s2 ——》老年代
2.栈(线程):适用于java方法嵌套调用逻辑顺序,
线程每调用一个方法就对应着 JVM Stack 中 Stack Frame 的入栈,方法执行完毕或者异常终止对应着出栈(销毁)
(1)栈帧:
1.局部变量表
2.操作数栈:操作栈调用其它有返回结果的方法时,会把结果 push 到栈上(通过操作数栈来进行参数传递)
3.动态链接
4.方法出口
3.本地方法栈:一个Native Method就是一个java调用非java代码的接口,
4.方法区(元空间),程序计数器
5.volatile关键字
java虚拟机提供的一种轻量级的同步机制,1.保证可见性,2.不保证原子性,3.禁止指令重排
1.jmm(java内存模型):可见,原子,有序
线程A 线程B
工作内存 工作内存
jmm来控制
主内存
(线程要对变量进行读写操作必须在工作内存中进行,首先从主内存中拷贝变量到工作空间,读写等操作完成之后再将变量写回主内存)
atomic类
6.cas(compareandswap)
为什么atomicIneger底层要用CAS而不是synchronized?
synchronized悲观锁,导致cpu的频繁的上下文切换效率很低
它是一条CPU并发原语,功能是判断内存中某个位置的值是否为预期值,如果是则更新为新的值,这个过程是原子性的
为CPU原子指令,不会造成所谓的数据不一致的问题
public void main (String[] args){AtomicInteger a=new AtomicInteger(5);System.out.pringln(a.compareAndSet(5,2020));System.out.pringln(a.compareAndSet(5,2021));a.getAndIncrement();/*源码:return unsafe.getAndAddInt(this,valueoffset,1);this:当前的对象,valueoffset:内存地址偏移量(内存地址),value:使用了volatile关键字保证了可见性public final int getAndAddInt(Object var1,long var2,int var4){int var5;do{/var5先获得当前对象的内存地址所指向的值也就类似于c和c++中的指针指向的值。var5 = this.getIntVolatile(var1, var2);//如果取到当前对象内存所指向的值是var5说明没有其他线程更改就把主内存中的值更改为var5 + var4,其中var4=1;}while(!this.compareAndSwapInt(var1,var2,var5,var5+var4))}用当前对象的值和var5比较如果相同,更新内存地址并返回true如果不同,继续取值再比较,直到更新完成(自旋锁的思想借鉴与之)即保证了一致性和高并发性*/
}
当线程获取主内存数据不是期望的5的时候就没有办法执行操作
2.cas的缺点:
如果cas一直失败,会给CPU带来很大的开销,只可以保证一个共享变量的原子操作,ABA问题
ABA问题:狸猫换太子
经典案例:
经典转账案例
假设小琳银行卡有 100 块钱余额,且假定银行转账操作就是一个单纯的 CAS 命令,对比余额旧值是否与当前值相同,如果相同则发生扣减/增加,我们将这个指令用 CAS(origin,expect) 表示。于是,我们看看接下来发生了什么:
- 小琳在 ATM 1 转账 100 块钱给小李;
- 由于ATM 1 出现了网络拥塞的原因卡住了,这时候小琳跑到旁边的 ATM 2 再次操作转账;
- ATM 2 没让小琳失望,执行了 CAS(100,0),很痛快地完成了转账,此时小琳的账户余额为 0;
- 小王这时候又给小琳账上转了 100,此时小琳账上余额为 100;
- 这时候 ATM 1 网络恢复,继续执行 CAS(100,0),居然执行成功了,小琳账户上余额又变为了 0;
- 这时候小王微信跟小琳说转了 100 过去,是否收到呢?小琳去查了下账,摇了摇头,那么问题来了,钱去了哪呢?
关于钱的去向,有一种可能就是小王给小琳的 100 大洋,因为 ATM 1 网络恢复再次被转给了小李,毕竟小琳尝试了两次转账,出现这种情况虽不合理,但情有可原。假设我们作为银行系统设计者和开发者,不接受这种情况存在,那我们就需要着手处理这种 ABA 问题了。
解决办法:添加一种新的机制,加上版本号(类似时间戳)
t1 100 1 2019 2
t2 100 1 101 2 100 3
7.ArrayList是线程不安全的,请编写一个不安全的案例并给出解决办法?
public class ArrayListTest {public static void main(String[] args) {List<String> test= new CopyOnWriteArrayList<>();for (int i = 0; i < 30; i++) {new Thread(()->{test.add(UUID.randomUUID().toString().substring(0,8));System.out.println(test);},String.valueOf(i)).start();}/** 出现异常:java.util.ConcurrentModificationException 并发修改异常* 导致原因* 并发争抢修改导致,参考花名册案例 一个同学正在写,另外一个同学过来抢夺,导致数据不一致异常,并发修改异常** 解决办法* 1.new Vector* 2.Collections.synchronizedList(new ArrayList<>())相当于外面套了一层锁* 3.new CopyOnWriteArrayList<>() 增删改加了锁(写时复制 案例 每个同学修改名单只有一支笔,修改后指针移到修改后的地址),读没有* CopyOnWrite并发容器用于读多写少的并发场景,比如白名单,黑名单之类的等等写搜索引擎设置哪些内容不可以搜索(黑名单)* 缺点比较占用内存,数据一致性问题,不能保持数据实时一致性,所以如果你希望写入的的数据,马上能读到,请不要使用CopyOnWrite容器* CopyOnWriteArrayList为什么并发安全且性能比Vector好我知道Vector是增删改查方法都加了synchronized,保证同步,但是每个方法执行的时候都要去获得锁,
* 性能就会大大下降,而CopyOnWriteArrayList 只是在增删改上加锁,
* 但是读不加锁,在读方面的性能就好于Vector,CopyOnWriteArrayList支持读多写少的并发情况。* 优化建议*** */}
}
ArrayList,set (hashset底层是hashmap),map线程不安全
ConcurrentHashMap,Vector,hashtable,stack是线程安全
java中8中基本类型和一种比较特殊的类型String
,常量池就是java系统级别提供的缓存
8.(java里面的锁)公平锁/非公平锁/可重入锁/递归锁/自旋锁谈谈你的理解?手写一个自旋锁?
(1)公平锁和非公平锁
公平锁是指:先来后到谁等待的时间长谁获得锁
对于java的来说默认的是非公平锁,非公平锁吞吐量比较大
非公平锁:非公平锁那就随机的获取,谁运气好,cpu时间片轮到哪个线程,哪个线程就能获取锁
(2)可重入锁(递归锁)synchronized ReenTrantLock
该锁支持同一个线程对资源的重复加锁
线程可以进入任意一个已经拥有锁的所同步的代码块
(3)自旋锁(unsafe类和CAS思想)手写自旋锁
尝试获取锁的线程不会立即阻塞,而是采用循环的方式来获取锁,减少线程上下文切换的消耗,但是会消耗CPU的资源
public class SpinLockDemo {AtomicReference<Thread> atomicReference=new AtomicReference<>();public void myLock(){Thread thread=Thread.currentThread();while (!atomicReference.compareAndSet(null,thread)){}System.out.println(thread.getName()+"\t come");}public void myunLock(){Thread thread=Thread.currentThread();atomicReference.compareAndSet(thread,null);System.out.println(thread.getName()+"\t invoked myunlock");}public static void main(String[] args) {SpinLockDemo spinLockDemo=new SpinLockDemo();new Thread(()->{spinLockDemo.myLock();try{TimeUnit.MICROSECONDS.sleep(1);}catch (InterruptedException e){e.printStackTrace();}spinLockDemo.myunLock();},"AA").start();try{TimeUnit.SECONDS.sleep(1);}catch (InterruptedException e){e.printStackTrace();}new Thread(()->{spinLockDemo.myLock();spinLockDemo.myunLock();},"BB").start();}
}
(4)独占锁/共享锁/互斥锁/读写锁
独占锁:该锁一次只可以被一个线程占用
共享锁:该锁可以被多个线程所持有
代码实现读写锁:
class MyCache{private volatile Map<String,Object> map=new HashMap<>();private ReentrantReadWriteLock readWriteLock=new ReentrantReadWriteLock(true);public void put(String key,Object value){readWriteLock.writeLock().lock();try {System.out.println(Thread.currentThread().getName()+"正在写入"+key);try{TimeUnit.SECONDS.sleep(3);}catch (InterruptedException e){e.printStackTrace();}map.put(key,value);System.out.println(Thread.currentThread().getName()+"写入完成");} catch (Exception e) {e.printStackTrace();} finally {readWriteLock.writeLock().unlock();}}public void get(String key){readWriteLock.readLock().lock();try {System.out.println(Thread.currentThread().getName()+"正在读取");try{TimeUnit.SECONDS.sleep(3);}catch (InterruptedException e){e.printStackTrace();}Object result=map.get(key);System.out.println(Thread.currentThread().getName()+"读取完成"+result);} catch (Exception e) {e.printStackTrace();} finally {readWriteLock.readLock().unlock();}}
}
public class ReadAndWriteLockDemo {public static void main(String[] args) {MyCache myCache=new MyCache();for (int i = 0; i < 5; i++) {final int temp=i;new Thread(()->{myCache.put(""+temp,""+temp);},String.valueOf(i)).start();}for (int i = 0; i < 5; i++) {final int temp=i;new Thread(()->{myCache.get(""+temp);},String.valueOf(i)).start();}}
}
9.CountDownLatch/CyclicBarrier/Semaphore使用过吗?
(1)CountDownLatch
public static void closeDoor() {try {CountDownLatch countDownLatch=new CountDownLatch(6);for (int i = 0; i < 6; i++) {new Thread(()->{System.out.println(Thread.currentThread().getName()+"------离开教室");countDownLatch.countDown();},String.valueOf(i)).start();}countDownLatch.await();System.out.println(Thread.currentThread().getName()+"*****锁门了");} catch (InterruptedException e) {e.printStackTrace();}
}
相当于一个线程的计数器,列入上面的代码来控制主线程最后执行
让一些线程阻塞知道另外一个线程完成一系列操作之后才会被唤醒
当计数器为0的时候,await()的线程才会被唤醒执行
(2)CyclicBarrier
相比较于CountDownLatch,CyclicBarrier是做加法,集齐七颗龙珠就可以召唤神龙
Cyclic:循环,Barrier:屏障
一组线程到达一个屏障(也可以叫做同步点)时被阻塞,直到最后一个线程到达屏障,屏障才会开门所有被屏障拦截的线程才会继续干活
试例代码
public class CyclicBarrierDemo {public static void main(String[] args) {CyclicBarrier cyclicBarrier = new CyclicBarrier(7, () -> {System.out.println("********召唤神龙");});for (int i = 1; i <= 7; i++) {final int temp = i;new Thread(() -> {System.out.println(Thread.currentThread().getName() + "收集到" + temp + "颗");try{cyclicBarrier.await();}catch (Exception e){e.printStackTrace();}}, String.valueOf(i)).start();}}
}
(3)Semaphore (主要 处理所线程抢占多个资源,也可以充当锁)
信号量的主要作用有两个,一个是用于多个共享资源的互斥使用,另外一个是用于并发线程数的控制
for example 抢车位代码
public class SemaphoreDemo {public static void main(String[] args) {Semaphore semaphore=new Semaphore(3);//三个停车场for (int i = 1; i < 6; i++) {new Thread(()->{try {semaphore.acquire();System.out.println(Thread.currentThread().getName()+"抢到车位");try {TimeUnit.SECONDS.sleep(3);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(Thread.currentThread().getName()+"停车3秒后离开");} catch (InterruptedException e) {e.printStackTrace();} finally {semaphore.release();}},String.valueOf(i)).start();}}
}
10.阻塞队列知道吗?
(1)阻塞队列有没有好的一面
(2)不得不阻塞,你如何管理
当阻塞队里是空的时候,从队列获取元素将会被阻塞
当阻塞队列是满的时候,往队列添加元素将会被阻塞
(3)BlockingQueue
1.ArrayBlockingQueue:由数组组成的有界阻塞队列
2.LinkedBlockindQueue:由链表结构组成的有界阻塞队列
3.PriorityBlockingQueue:支持优先级排序的无界阻塞队列
4.delayQueue:使用优先级实现延迟无界阻塞队列
5.SynchronousQueue:不存储单个元素的阻塞队列,也即单个元素队列
6.LinkedTransferQueue:由链表结构组成的阻塞队列
7.LinkedBlockingQueue:由链表结构组成的双向阻塞队列
(4)BlockingQueue API
1.返回值是布尔类型
抛出异常 | 特殊值 | 阻塞 | 超时 | |
---|---|---|---|---|
插入 |
add(e)
|
offer(e)
|
put(e)
|
offer(e, time, unit)
|
移除 |
remove()
|
poll()
|
take()
|
poll(time, unit)
|
检查 |
element()
|
peek()
|
不可用 | *不可用 * |
2.用在哪里
生产消费者模式
1.传统版,
题目:一个初始值为零的变量,两个线程对其交替操作,一个加1,一个减1,来5轮
public class ProductConsumer_traditionDemo {public static void main(String[] args) {ShareData shareData=new ShareData();new Thread(()->{for (int i = 1; i <=5 ; i++) {try {shareData.increment();} catch (Exception e) {e.printStackTrace();}}},String.valueOf("AA")).start();new Thread(()->{for (int i = 1; i <=5 ; i++) {try {shareData.decrement();} catch (Exception e) {e.printStackTrace();}}},String.valueOf("BB")).start();} } class ShareData{private int number=0;private Lock lock = new ReentrantLock(true);private Condition condition=lock.newCondition();public void increment(){lock.lock();try {while (number!=0){condition.await();}number++;System.out.println(Thread.currentThread().getName()+"\t"+number);/*唤醒线程*/condition.signalAll();} catch (Exception e) {e.printStackTrace();}finally {lock.unlock();}}public void decrement(){lock.lock();try {while (number==0){condition.await();}number--;System.out.println(Thread.currentThread().getName()+"\t"+number);/*唤醒线程*/condition.signalAll();} catch (Exception e) {e.printStackTrace();}finally {lock.unlock();}} }
(注意)java多线程为什么要使用while而不是使用if
问题的关键点在于wait方法执行之后,notify是从那里开始执行,如果是if的话第一次会执行if判断,第二次唤醒就会执行if下面内容
补充
2.阻塞队列版(高并发版本)
class MyResource{private volatile boolean flag=true;private AtomicInteger atomicInteger=new AtomicInteger();BlockingQueue<String> blockingQueue=null;public MyResource(BlockingQueue<String> blockingQueue) {this.blockingQueue = blockingQueue;System.out.println(blockingQueue.getClass().getName());}public void prod() throws Exception{String data=null;boolean resultValue;while (flag){data=atomicInteger.incrementAndGet()+"";resultValue = blockingQueue.offer(data, 2L, TimeUnit.SECONDS);if(resultValue){System.out.println(Thread.currentThread().getName()+"\t"+"插入数据成功"+data);}else{System.out.println(Thread.currentThread().getName()+"\t"+"插入数据失败"+data);}TimeUnit.SECONDS.sleep(1);}System.out.println(Thread.currentThread().getName()+"\t flag=false ,生产动作停止");}public void myconsumer() throws Exception{String data=null;while (flag){data=blockingQueue.poll(2L,TimeUnit.SECONDS);if(data==null||data.equalsIgnoreCase("")){flag=false;System.out.println(Thread.currentThread().getName()+"\t 消费退出");return;}System.out.println(Thread.currentThread().getName()+"\t 消费数据成功"+data);}}public void stop() throws Exception{this.flag=false;} } public class Product_ConsumerDemo {public static void main(String[] args) throws Exception{MyResource myResource=new MyResource(new ArrayBlockingQueue<>(10));new Thread(()->{System.out.println(Thread.currentThread().getName()+"\t 生产线程启动");try {myResource.prod();} catch (Exception e) {e.printStackTrace();}},"Prod").start();new Thread(()->{System.out.println(Thread.currentThread().getName()+"\t 消费线程启动");try {myResource.myconsumer();} catch (Exception e) {e.printStackTrace();}},"Consumer").start();try { TimeUnit.SECONDS.sleep(5); } catch (InterruptedException e) { e.printStackTrace(); }System.out.println("over");myResource.stop();} }
线程池
消息中间件
11.线程池有使用过吗,ThreadPoolExecutor谈谈你的理解(第四种获得java多线程的方式)
1.为什么要使用线程池
- 降低资源消耗
- 提高相应速度
- 提高线程的可管理
2.线程池如何使用
首先java中的线程池是通过Executor框架实现,该框架中用到了Executor,Executors(辅助工具类),ExecutorService,ThreadPoolExecutor(最主要的)
ExecutorService threadPool= Executors.newCachedThreadPool();
ExecutorService threadPool= Executors.newFixedThreadPool(5);
ExecutorService threadPool= Executors.newSingleThreadExecutor();
3.说说线程池几个重要的参数
ThreadPoolExecutor中7个参数:
corePoolSize:线程池中常驻核心线程数
maximumPoolSize:线程池可以容纳同时执行的最大线程数,此值必须大于等于1
keepAliveTime:多余空闲线程的存活时间(当前线程池线程数量超过corePoolSize,当空闲时间大于keepAliveTime,多余线程会被销毁直至达到corePoolSize)
unit:keepAliveTime的时间单位
workQueue:任务队列(阻塞队列,类似于银行的候客区)
threadFactory:生成线程池工厂
handler:拒绝策略(默认四种方法,最大线程数和阻塞队列都满了会执行拒绝策略)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-W239ypVW-1666103904161)(D:\Typora\pic\Snipaste_2021-01-14_08-47-36.png)]
4.说说线程池的底层原理(略)
5.线程资源必须通过线程池提供,不允许在应用中自行显示创建线程
6.你在工作中是如何使用线程池的,是否自定义过线程池的使用
7.在线程池中配置合理的线程数
cpu密集型,io密集型
12.synchronized和Lock有什么区别
1.原始构成
synchronized是关键字属于jvm层面,LOCK是具体类是api层面的锁
2.使用方法
synchronized不需要用户手动的释放锁,lock则需要用户手动的释放锁
3.等待是否可中断
synchronized是不可中断的,除非异常或者正常执行完成,lock 可中断
4.加锁是否公平
5.锁要绑定多个condition
synchronized 没有
ReentrantLock用来实现分组唤醒需要唤醒的线程,可以精确唤醒
for example:
题目:所线程之间按照顺序调用,实现A-》B-》C三个线程启动
public class SyncAndReentrantDemo {public static void main(String[] args) {ShareResource shareResource=new ShareResource();new Thread(()->{for (int i = 1; i <=10 ; i++) {shareResource.print5();}},"AA").start();new Thread(()->{for (int i = 1; i <=10 ; i++) {shareResource.print10();}},"BB").start();new Thread(()->{for (int i = 1; i <=10 ; i++) {shareResource.print15();}},"CC").start();}
}
class ShareResource{private int number =1;//a:1 b:2 c:3private Lock lock=new ReentrantLock();private Condition c1=lock.newCondition();private Condition c2=lock.newCondition();private Condition c3=lock.newCondition();public void print5(){lock.lock();try {while (number!=1){c1.await();}for (int i = 1; i <=5 ; i++) {System.out.println(Thread.currentThread().getName()+"\t"+i);}number=2;c2.signal();} catch (Exception e) {e.printStackTrace();} finally {lock.unlock();}}public void print10(){lock.lock();try {while (number!=2){c2.await();}for (int i = 1; i <=10 ; i++) {System.out.println(Thread.currentThread().getName()+"\t"+i);}number=3;c3.signal();} catch (Exception e) {e.printStackTrace();} finally {lock.unlock();}}public void print15(){lock.lock();try {while (number!=3){c3.await();}for (int i = 1; i <=15 ; i++) {System.out.println(Thread.currentThread().getName()+"\t"+i);}number=1;c1.signal();} catch (Exception e) {e.printStackTrace();} finally {lock.unlock();}}
}
13.死锁编码及定位分析
1.定义:两个及两个以上的线程的在执行的过程中,因争夺资源而造成的一种相互等待的现象
class HoldLockThread implements Runnable{private String LockA; private String LockB;public HoldLockThread(String lockA, String lockB) {LockA = lockA;LockB = lockB;}@Overridepublic void run() {synchronized (LockA){System.out.println(Thread.currentThread().getName()+"持有的"+LockA+"尝试获得的"+LockB);try {TimeUnit.SECONDS.sleep(2);} catch (InterruptedException e) {e.printStackTrace();}synchronized (LockB){System.out.println(Thread.currentThread().getName()+"持有的"+LockB+"尝试获得的"+LockA);}}}
}
public class DeadLockDemo {public static void main(String[] args) {String LockA="lockA";String LockB="lockB";new Thread(new HoldLockThread(LockA,LockB),"ThreadAAA").start();new Thread(new HoldLockThread(LockB,LockA),"ThreadBBB").start();}
}
2.解决办法
jps定位进程号
jstack找到死锁查看
14.jvm垃圾回收的时候如何确定垃圾? 是否知道GC Roots?
枚举根节点做可达性分析(根搜索路径)
GC Roots的对象作为起始点,从GC Roots对象开始向下搜索,如果一个对象没有任何引用链接的时候,表明该对象不可使用
(1)jvm中可以作为GC Roots的对象有哪些?
- 1.虚拟机栈中引用的对象
- 2.方法区中类静态属性引用的对象
- 3.方法区中常量引用的对象
- 4.本地方法栈中JNI(即一般说的Native方法)的引用对象
15,你说过你做过jvm调优和参数配置,请问如何盘点查看jvm系统默认值?
(1)jvm参数类型
1.标配参数
-version
-help
java -showversion
2.X参数(了解)
-Xint 解释执行
-Xcomp 第一次使用就编译本地代码
-Xmixed 混合模式
3.XX参数
boolean类型 :公式: -XX:+或者-某个属性值(+表示开启,-表示关闭)
是否打印GC收集细节(PrintGCDetails) 、是否使用串行垃圾回收器(UseSerialGC)
kv设值类型:公式:-XX:属性key=属性value
for example:-xx:MetaspaceSize=1024m(元空间的大小) -xx:MaxTenuringThreshold=15(eden区存活15轮)
jinfo举例
4.两个经典参数
-Xms (等价于 -XX:InitalHeapSize) -Xmx (等价于 -XX:MaxHeapSize )
(2)如何查看一个正在运行的java程序,它的某个jvm参数是否开启?具体指是多少?
- (1)第一种:
使用jps和jinfo的命令来查看
jinfo -flag 具体参数 java进程编号
- (2)第二种方法
-XX:+PrintFlagIntial:主要查看默认的初始值,公式:java -XX:+PrintFlagIntial -version
-XX:+PrintFlagFinal:主要查看修改更新过后的参数值
15.你平时工作中jvm常用基本配置参数有哪些?
- -Xms:初始内存大小,默认为物理内存的 1/64
- -Xmx:最大分配内存,默认为物理内存的1/4
- -Xss:设置单个线程栈的大小,一般为512k~1024k
- -Xmn:设置年轻代的大小
- -xx:MetaspaceSize=1024m(元空间的大小)
- -XX:+PrintGCDetails (-Xmx10m -Xms10m -XX:+PrintGCDetails)
- -XX:SurvivorRatio:设置新生代中Eden和S0、S1的空间比例,默认是8:1:1
- -XX:NewRatio:设置年轻代和老年代在堆结构的占比
-XX:MaxTenuringThreShold:设置垃圾最大的年龄,如果设置为0则年轻代对象不会经过Survivor区,对于老年代对象比较多的应用可以提高效率
16.强引用,软引用,弱引用,虚引用作用分别是什么?
- 1.强引用:jvm开始垃圾回收的时候,就算出现OOM对于强引用对象也不进行回收,死都不回收,一般new出来的对象都是强引用
- 2.软引用:内存足够的时候不回收,内存不够的时候回收,软引用通产用在对内存敏感的程序中,比如高速缓存,使用泛型SoftReference;可以通过get方法获得强引用
- 3.弱引用:只要执行GC就会被回收 需要使用java.lang.WeekReference类来实现,你知道WeekHashMap吗?键值为null时候gc会被回收
- 4.虚引用:任何时候都可能被垃圾回收器回收,gc后被放到引用队列中
17.请谈谈对OOM的认识?
StackOverFlowError:栈溢出异常,递归调用
OutofMemoryError:(1)java heap space (2)GC overhead limit exceeded :GC时间过长
(3)Direct buffer memory:例子:使用NIO的byteBuffer来读取或者写入数据
(4)unable to create new native thread 不能创建更多的本地线程
导致原因(1)应用创建了太多的线程 (2)服务器不允许创建这么多的线程,linux上默认允许单个进程创建的线程数量是1024个
(5)Metaspace 元空间不足
18.GC垃圾回收算法和垃圾回收器的关系?分别是什么请你谈谈
1.垃圾回收算法:
引用计数、复制、标记、标整、分代收集
2.四种垃圾回收器
1.serial 2.parallel 3.CMS 4.G1
19.如何查看服务器上默认的垃圾回收器是哪个?生产上是如何配置垃圾回收器的?谈谈你对垃圾回收器的理解?
20 jvmGC结合springboot微服务生产部署调优
…
21.生产环境服务器变慢,诊断思路和性能评估谈谈?
(1)整机 top
load average: 0.58, 0.41, 0.30 系统负载,即任务队列的平均长度。 三个数值分别为 1分钟、5分钟、15分钟前到现在的平均值。 如果这个数除以逻辑CPU的数量,结果高于5的时候就表明系统在超负荷运转了。 (2)CPU vmstat
vmstat -n 2 3 (2秒时间刷新间隔,刷新3次)
(3)内存:free
free -m 查看系统内存占用情况
pidstat -p 进程号 -r 采样间隔秒数
(4)硬盘:df (查看磁盘剩余空间)df -h
(5)磁盘 IO iostat
(6)网络IO ifstat
22.假如生产环境CPU占用率过高,解决办法
- (1)使用TOP命令来找出CPU占比最高的进程
- (2)ps -ef 或者JPS进一步定位,得知是怎样一个后台程序
- (3)定位到具体的线程或者代码
- (4)将需要的线程id转化为16进制格式
- (5)jstack进程ID
23.对于jdk自带的jvm监控和性能分析工具用过哪些?
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-R8JTJiCt-1666103904162)(D:\Typora\pic\20200925125200430.png)]
24.github
1.常用词含义
(1)watch:会持续收到该项目的动态
(2)fork:赋值某个项目到自己的gitlab仓库中
(3)star:点赞
(4)clone:
(5)follow:
2.github常用命令
一般情况下git命令都是 git [command] [option] [argument]
git config --golobal user.name=“hic” 其中config指的就是配置命令 其中–global指的是对全局配置生效
3.in关键词搜索
xxx in:name 项目名包含XXX的,readme,description
4.star或者fork关键字搜搜
(1)公式:xxx关键词 star 通配符 :>或者:>= 区间范围 数字1…数字2
(2)查找stars数量大于5000的springboot项目 springboot stars:>5000
组合模式:springboot forks:100…200 stars:80…100
(3)awesome:awesome系列一般是用来收集学习,工具,书籍类的项目
(4)高亮显示 地址后面 #L行数-L行数
(5)项目内搜索 键盘英文t
25.字符串常量java内部加载
string::intern()是一个本地的方法,它的作用的是如果字符串常量池中已经包含了一个等于此String对象,则返回该对象的引用;
否则将会把此String对象包含的字符串添加到常量池中,并返回此String对象的引用。
Stirng str=new StringBuffer(“ja”).append(“va”).toString();
sout(str); sout(str.intern());sout(str==str.intern());
why:只有java显示的是false??有个初始化的java字符串然后进入常量池
26.AQS原理
1.可重入锁:是指同一个对象在外层方法获取锁后,再进入内层方法会自动获取锁(前提,锁对象是同一个对象),不会因为没有释放锁而导致阻塞防止发生死锁
2.可重入锁的种类:1.隐式锁 2.显示锁
3.locksupport:线程等待唤醒机制(wait/notify)
locksupport中的park()和unpark()的作用分别是阻塞线程和解除阻塞线程,locksupport类使用了一种命名为permit的概念来做到阻塞和唤醒线程的功能,每一个线程都有一个permit,permit只有两个值 0,1
为什么说AQS是JUC内容中最重要的基石?
27.什么是进程\线程\并发\并行
java面试一些问题汇总相关推荐
- 阿里最全Java面试100题汇总:涵盖天猫、蚂蚁金服等面试题!含答案~
[阿里天猫.蚂蚁.钉钉面试题目] 1.微信红包怎么实现. 2.海量数据分析. 3.测试职位问的线程安全和非线程安全. 4.HTTP2.0.thrift. 5.面试电话沟通可能先让自我介绍. 6.分布式 ...
- Java面试通关要点汇总集(基础篇之基本功,非原作者)
Java面试通关要点汇总集(部分解答) 说明 如果你有幸能看到的话, 1.本文整体框架来自@阿里.梁桂钊的博文,总结的非常不错.值得我们学习,它的博客部分做了解答. 2.由于自己能力有限,没能实现心中 ...
- Java面试通关要点汇总集【终极版】
原文地址:梁桂钊的博客 博客地址:blog.720ui.com 年前,我整理的 Java面试通关要点汇总集 获得了很多读者的肯定,谢谢大家支持.事实上,笔者结合自己过往的面试经验,整理了一些核心的知识 ...
- java面试笔试大汇总(一)
java面试笔试题大汇总5 JAVA相关基础知识 1.面向对象的特征有哪些方面 1.抽象:2.继承:3.封装:4. 多态性: 2.String是最基本的数据类型吗? 基本数据类型包括byte.int. ...
- Java面试题目大汇总(附参考答案)
足足准备了长达3个月的面试,终于在上周拿到了阿里的offer! 博主汇总整理了一份我面试之前看的一些Java面试题目,可以说是非常详细! 分享给大家,希望对正在面试Java岗位的朋友有帮助哈~~ (文 ...
- 史上最全阿里Java面试题目大汇总!强烈建议收藏~
阿里面试题目目录 技术一面(基础面试题目) 技术二面(技术深度.技术原理) 项目实战(项目模拟面试) JAVA开发技术常问的问题 阿里必会知识 阿里面试范畴 阿里面试总结 一:阿里技术一面(基础掌握牢 ...
- java面试高频知识点汇总 2021-02-24
杂碎知识点1 大四开始找工作后遇到的面试题进行汇总,因为之前记录的都是在有道云中,复制到简书出现格式的问题,大致修补了一下,后续继续上传. 1.Integer缓存池问题 当给Integer赋值在-12 ...
- Java开发者跳槽必备:2021阿里Java面试题目大汇总
5.高并发 6.中间件 7.之前项目经历,运用的技术,遇到的问题,如何解决,个人有什么收获和成长: 8.对于技术的热情(平时是否看些技术书籍,逛论坛,写博客,写源代码或程序等): JAVA开发技术面试 ...
- Java面试通关要点汇总集(山东数漫江湖)
这里,笔者结合自己过往的面试经验,整理了一些核心的知识清单,帮助读者更好地回顾与复习 Java 服务端核心技术.本文会以引出问题为主,后面有时间的话,笔者陆续会抽些重要的知识点进行详细的剖析与解答.敬 ...
- Java面试通关要点汇总集之核心篇参考答案
2019独角兽企业重金招聘Python工程师标准>>> 数据存储 MySQL 索引使用的注意事项 1.索引不会包含有NULL的列 只要列中包含有NULL值,都将不会被包含在索引中,复 ...
最新文章
- mapx实现热点效果
- C#Winform控件随窗体缩放
- httpwatchv11.1.46.0免费版
- Webbench网站压力测试
- 任务间通信的基本知识
- DHCP 服务原理:Snooping和Relay
- CentOS7.5下搭建zabbix3.4监控
- CF1444C Team-Building(可持久化并查集)(二分图)
- java圆形头像上传_Android自定义控件实例,圆形头像(图库 + 裁剪+设置),上传头像显示为圆形,附源码...
- python网络编程基础语法_python网络编程
- Html前端基础(这些基础标签你必须知道!)
- 目标成为Photoshop的轻量级替代软件——Acorn Mac版
- Swift基础语法: 21 - Swift的可变形形参, 常量形参, 变量形参, In-Out形参
- Proteus仿真Arduino的Proteus Library文件下载
- (三)进程各种id:pid、pgid、sid、全局pid、局部pid
- 通过PS抠出透明的玻璃瓶
- dummy node
- 苹果iOS 8.0正式发布啦
- 工业机器人组成结构【拆卸 / 组装 KUKA 工业机器人】
- 七牛 savekey php,七牛云1:客户端直接上传文件