Java面经总结

线程安全

1.什么是不安全?
 1.1 不同线程,对同一资源的访问或修改。
 1.2 原子性   JVM规范定义了线程对主存的操作指令:read,load,use,assign,store,write
 1.3 可见性------------------------------------------------volatile,final,synchronized,
 1.4 有序性-------------read-load,从主存加载数据到线程自己的工作内存中,即保留一个副本,assign,修改之后, 变量副本会同步到主存储区(store- write),何时同步不一定,导致最后在内存中的值不是想象中的。
2.为什么会产生?
 1. CPU高速缓存
 2、主内存
3.如何避免?
1.强同步:synchronized 关键字。 当一段代码会修改共享变量,这一段代码成为互斥区或临界区,用synchronized标识起来,共享对象作为锁,否则没有意义。
     每个锁对象都有两个队列,一个是就绪队列,一个是阻塞队列,就绪队列存储了将要获得锁的线程,阻塞队列存储了被阻塞的线程,当一个被线程被唤醒 (notify)后,才会进入到就绪队列,等待cpu的调度

一个线程执行临界区代码过程如下:
1 获得同步锁
2 清空工作内存
3 从主存拷贝变量副本到工作内存
4 对这些变量计算
5 将变量从工作内存写回到主存
6 释放锁

2.生产者/消费者模式
      lock.wait   -----释放锁,
      lock.notify  ----通知lock中阻塞队列里面的某个线程,进入就绪队列。
      lcok.notifyAll ---通知所有阻塞队列里的线程。


    3.volitle
      对变量修改回写到内存,相当于 (store- write)
       防止指令重排

    4.共享对象不可变

     5.原子操作,原子类,底层CAS实现,但是会导致缓存一致性流量,bus风暴,性能降低
            MESI协议实现,

底层实现:

 1.read,load,assign,use,store,write (底层原子操作)
 2.lock,unlock.开放api给用户用,字节码为monitorenter,monitorexit   (Syncronized 关键字的底层)
   其实是对象头,包含一个锁的位置:
对象头:

http://blog.csdn.net/hsuxu/article/details/9472371
这里写图片描述
包含,锁的升级,可升不可降

各种锁:

1. ReentrantLock
在同步竞争不激烈时用synchronized,激烈时用ReentrantLock
 ReentrantLock提供了lockInterruptibly()方法可以优先考虑响应中断,而不是像synchronized那样不响应interrupt()操作
同一个线程,持有锁,可以重新获取该锁,即重进入,避免了死锁,内部实现有一个计数器和一个标志位,标志占有的线程。
需要手动释放锁

2.synchronized + 内部锁,或叫互斥锁,会阻塞或等待,直到获取锁,无法重进入,产生死锁
     +static 类锁


3.公平锁,非公平锁
          公平锁是指多个线程在等待同一个锁时,必须按照申请锁的先后顺序来一次获得锁。
4.自旋锁
      线程执行一个忙循环(自旋),等待其他线程释放锁。
5.其他
![这里写图片描述](https://img-blog.csdn.net/20160912192430196)

并发工具

一.CountDownLatch用法

await()
await(long timeout,TimeUnit unit)
countDown();
二.CyclicBarrier用法

await()
await(long timeout,TimeUnit unit)
   第一个版本比较常用,用来挂起当前线程,直至所有线程都到达barrier状态再同时执行后续任务;
  第二个版本是让这些线程等待至一定的时间,如果还有线程没有到达barrier状态就直接让到达barrier的线程执行后续任务。
三.Semaphore用法

1
2
3
4
public void acquire() throws InterruptedException {  }     //获取一个许可
public void acquire(int permits) throws InterruptedException { }    //获取permits个许可
public void release() { }          //释放一个许可
public void release(int permits) { }    //释放permits个许可

控制资源能够被多少线程访问,类似于锁。

class 加载

双亲委派模型的工作流程是:如果一个类加载器收到了类加载的请求,它首先不会自己去尝试加载这个类,而是把请求委托给父加载器去完成,依次向上,因此,所有的类加载请求最终都应该被传递到顶层的启动类加载器中,只有当父加载器在它的搜索范围中没有找到所需的类时,即无法完成该加载,子加载器才会尝试自己去加载该类。

c++——-> bootstrap classloader ———->extension classloader —-> application classloader ——–>selfdefined classloader

垃圾回收

这里写图片描述

1. new Object --> eden , if not enough ---> YoungGC(Minor GC)
2. Survivor Mem not enough ---> YoungGC(Major GC    : Old Generation)
3. Old Generation Mem not enough ---> Full GC  (Old: CMS)
引用算法:

引用分类:强,软,弱,虚

1.引用计数, 存在循环引用
2.可达性分析算法,即判断一个对象能否到达GC-roots,GC-roots:
虚拟机栈(栈帧中的本地变量表)中引用的对象。
方法区中类静态属性引用的对象。
方法区中常量引用的对象。
本地方法栈中JNI(即一般说的Native方法)引用的对象。
垃圾收集算法:

1.标记-清除  ,直接清除当前位置。
2.复制算法   即复制到另一半,然后回收另一半,一块大eden区,两块小survivor区,将eden区中存活的复制到一块空的survivor区,清理eden和第一个survivor
3.标记-整理,然所有存活对象移动到另一端,清除另一端。
4.分代收集

5.hot-spot的实现:

          各个收集器。采用不同的垃圾收集算法
          5.1 serial 收集器,单线程,新生代收集器,标记-整理
          5.2 ParNew,多线程的serial。
          5.3 Parallel Scavenge,新生代,复制算法。
          5.4 serial-old
          5.5 ParalleOld
          5.6 CMS,很短暂的停顿。不会stop the world,标记-清除

eden----> survivor--->old---->perm
年龄,大对象,往后放

6.G1收集器,牛逼,即 将jvm的堆区,划分为大小相等的region,remembered Set (referrence counting)

分为以下4各阶段:
初始标记(GCroots)
并发标记
最终标记
筛选回收
1 .分代收集:仍然有分代的概念,不需要其他收集器配合,独立管理整个GC堆。
2 .空间整合:从整体看,是基于“标记-整理”算法实现的,从局部(两个Region之间)看是基于“复 制”算法的。在运行期间不会产生内存碎片。
3 .可预测的停顿:G1跟踪各个Region里垃圾堆积值的价值大小,维护一个优先级队列,每次根据允许 的时间,优先回收价值最大的Region。(这也是Garbage First的由来)

虚拟机GC参数设置

http://unixboy.iteye.com/blog/174173
-Xms   
-Xmx   JVM 最大内存
-Xmn   年轻代大小

-XX:SuvirorRatio=8  eden:survivor = 8:1
-XX:PretenureSizeThreshold   设置大对象阈值,超过,则直接分配到老年代 只对 parnew 和Serail 收集器有效
-XX:MaxPretenuringThreshold 设置晋升old的阈值  即age的max

-XX:+UseParNewGC:
-XX:+UseG1GC

eden --> survivor age:1
minor GC, age ++
if age >= 15 ----> Old Generation

Class:

这里写图片描述

1.Magic Num :0xCAFFEBABE
2.constant_pool :

    1. literal
    2. reference name

底层进阶:

线程实现

1.使用内核线程实现(KLT)。由内核分配,内核Scheduler调度。 但一般用LWP(轻量级进程),即KLT的一种接口。(user mode ,kernel mode切换消耗资源)

这里写图片描述

2.使用用户线程实现

这里写图片描述

3.LWP和用户线程混合
这里写图片描述
SunJdk中用LWP(win,linux)

线程调度(java,抢占式)

这里写图片描述

常见集合原理源码

这里写图片描述

Map系: HashMap,LinkedHashMap,TreeMap, WeakHashMap, EnumMap,ConcurrentHashMap

List系:ArrayList, LinkedList, Vector, Stack

Set系:HashSet, LinkedHashSet, TreeSet
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java面经是指在面试过程中常被问到的与Java相关的问题和知识点。下面是一些常见的Java面经问题及其解答: 1. Java的特点是什么? Java是一种面向对象的编程语言,具有跨平台性、简单性、可靠性、安全性和高性能等特点。 2. 什么是Java虚拟机(JVM)? JVMJava程序运行的环境,它负责将Java源代码编译成字节码,并在不同的操作系统上执行。 3. 什么是面向对象编程(OOP)? 面向对象编程是一种编程范式,它将数据和操作数据的方法封装在一起,通过创建对象来实现程序的功能。 4. Java中的四种访问修饰符分别是什么? Java中的四种访问修饰符分别是public、protected、default和private,用于控制类、方法和变量的访问权限。 5. 什么是Java中的异常处理机制? 异常处理机制是Java中用于处理程序运行过程中出现的异常情况的一种机制,通过try-catch-finally语句块来捕获和处理异常。 6. 什么是Java中的多线程? 多线程是指在一个程序中同时执行多个线程,每个线程都可以独立执行不同的任务,提高程序的并发性和效率。 7. 什么是Java中的集合框架? 集合框架是Java中用于存储和操作一组对象的类库,包括List、Set、Map等常用的数据结构和算法。 8. 什么是Java中的反射机制? 反射机制是指在运行时动态地获取和操作类的信息,可以通过反射来创建对象、调用方法和访问属性等。 9. 什么是Java中的IO流? IO流是Java中用于输入和输出数据的一种机制,包括字节流和字符流,用于读取和写入文件、网络等数据源。 10. 什么是Java中的设计模式? 设计模式是一种解决常见软件设计问题的经验总结,包括单例模式、工厂模式、观察者模式等常用的设计模式。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值