1、JVM 运行时内存
Java 堆从 GC 的角度还可以细分为: 新生代(Eden 区、 From Survivor 区和 To Survivor 区)和老年代。
新生代
是用来存放新生的对象。一般占据堆的 1/3 空间。由于频繁创建对象,所以新生代会频繁触发MinorGC 进行垃圾回收。新生代又分为 Eden区、 ServivorFrom、 ServivorTo 三个区。
Eden 区
Java 新对象的出生地(如果新创建的对象占用内存很大,则直接分配到老年代)。当 Eden 区内存不够的时候就会触发 MinorGC,对新生代区进行一次垃圾回收。
ServivorFrom
上一次 GC 的幸存者,作为这一次 GC 的被扫描者。
ServivorTo
保留了一次 MinorGC 过程中的幸存者。
MinorGC 的过程(复制->清空->互换)
MinorGC 采用复制算法。
eden、 servicorFrom 复制到 ServicorTo,年龄+1
首先,把 Eden 和 ServivorFrom 区域中存活的对象复制到 ServicorTo 区域(如果有对象的年龄以及达到了老年的标准,则赋值到老年代区),同时把这些对象的年龄+1(如果 ServicorTo 不够位置了就放到老年区);
清空 eden、 servicorFrom
然后,清空 Eden 和 ServicorFrom 中的对象;
ServicorTo 和 ServicorFrom 互换
最后, ServicorTo 和 ServicorFrom 互换,原 ServicorTo 成为下一次 GC 时的 ServicorFrom区。
2、如果你提交任务时,线程池队列已满,这时会发生什么
这里区分一下:
1、 如果使用的是无界队列LinkedBlockingQueue,也就是无界队列的话,没关系,继续添加任务到阻塞队列中等待执行,因为LinkedBlockingQueue可以近乎认为是一个无穷大的队列,可以无限存放任务
2、 如果使用的是有界队列比如ArrayBlockingQueue,任务首先会被添加到ArrayBlockingQueue中,ArrayBlockingQueue满了,会根据maximumPoolSize的值增加线程数量,如果增加了线程数量还是处理不过来,ArrayBlockingQueue继续满,那么则会使用拒绝策略RejectedExecutionHandler处理满了的任务,默认是AbortPolicy
3、永久代
指内存的永久保存区域,主要存放 Class 和 Meta(元数据)的信息,Class 在被加载的时候被放入永久区域, 它和和存放实例的区域不同,GC不会在主程序运行期对永久区域进行清理。所以这也导致了永久代的区域会随着加载的 Class 的增多而胀满,最终抛出 OOM 异常。
4、什么是不可变对象,它对写并发应用有什么帮助?
1、 不可变对象(Immutable Objects)即对象一旦被创建它的状态(对象的数据,也即对象属性值)就不能改变,反之即为可变对象(Mutable Objects)。
2、 不可变对象的类即为不可变类(Immutable Class)。Java平台类库中包含许多不可变类,如String、基本类型的包装类、BigInteger和BigDecimal等。
3、 不可变对象天生是线程安全的。它们的常量(域)是在构造函数中创建的。既然它们的状态无法修改,这些常量永远不会变。
1、 不可变对象永远是线程安全的。
2、 只有满足如下状态,一个对象才是不可变的;
3、 它的状态不能在创建后再被修改;
4、 所有域都是final类型;并且,
5、 它被正确创建(创建期间没有发生this引用的逸出)。
5、什么是多线程的上下文切换
多线程的上下文切换是指CPU控制权由一个已经正在运行的线程切换到另外一个就绪并等待获取CPU执行权的线程的过程。
6、Java的内存模型是什么?(JMM是什么?)
JVM试图定义一种统一的内存模型,能将各种底层硬件及操作系统的内存访问差异进行封装,使Java程序在不同硬件及操作系统上都能达到相同的并发效果。它分为工作内存和主内存,线程无法对主存储器直接进行操作,一个线程要和另外一个线程通信,只能通过主存进行交换。
JMM可以说是Java并发的基础,它的定义将直接影响多线程实现的机制,如果你想要想深入了解多线程并发中的相关问题现象,对JMM的深入研究是必不可少的。
上面两个问题是经常容易搞混的,但它们的内容却完全不同的。
[7、Collections.synchronized 是什么?](https://gitee.com/souyunku/DevBooks/blob/master/docs/并发编程/并发编程高级面试题及答案,企业真面试题.md#7collectionssynchronized- 是什么)
**注意:_ 号代表后面是还有内容的_
此方法是干什么的呢,他完完全全的可以把List、Map、Set接口底下的集合变成线程安全的集合
Collections.synchronized * :原理是什么,我猜的话是代理模式:
8、在 Java 程序中怎么保证多线程的运行安全?
出现线程安全问题的原因一般都是三个原因:
1、 线程切换带来的原子性问题 解决办法:使用多线程之间同步synchronized或使用锁(lock)。
2、 缓存导致的可见性问题 解决办法:synchronized、volatile、LOCK,可以解决可见性问题
3、 编译优化带来的有序性问题 解决办法:Happens-Before 规则可以解决有序性问题
9、怎么获取 Java 程序使用的内存?堆使用的百分比?
可以通过 java.lang.Runtime 类中与内存相关方法来获取剩余的内存,总内存及最大堆内存。通过这些方法你也可以获取到堆使用的百分比及堆内存的剩余空间。Runtime.freeMemory() 方法返回剩余空间的字节数,Runtime.totalMemory()方法总内存的字节数,Runtime.maxMemory() 返回最大内存的字节数。
10、你如何确保main()方法所在的线程是Java 程序最后结束的线程?
我们可以使用Thread类的join()方法来确保所有程序创建的线程在main()方法退出前结束。