Java基础(JVM垃圾回收+synchronized)

2023-12-19 11:26:06 浏览数 (1)

1.关于Java的一些概念,下面哪些描述是正确的(BF)

A. 所有的Java异常和错误的基类都是java.lang.Exception,包括java.lang.RuntimeException

​ A错误的关键在与异常和错误的区分,Java中所有异常和错误的父类是java.lang.Throwable;错误类的基类是java.lang.Error,异常类的基类是java.lang.Exception.

B. 通过try… catch … finally语句,finally中的语句部分无论发生什么异常都会得到执行
C. java中所有的数据都是对象
D. Java通过垃圾回收回收不再引用的变量,垃圾回收时对象的finalize方法一定会得到执行

​ 描述部分正确,部分错误。

​ 首先,Java的垃圾回收机制确实是通过回收不再被引用的对象来释放内存的。在Java中,所有的对象都是在堆内存中分配的。当一个对象被创建时,Java运行时环境就会在堆内存中为其分配一块内存空间。当这个对象不再被任何强引用所指向时,Java垃圾回收器就会视为这个对象可以被回收,从而尝试回收它所占用的内存空间。

但是,垃圾回收时对象的finalize方法是否一定会得到执行,则不能一概而论。

​ 在Java中,每个对象都有一个finalize方法,这个方法在对象被垃圾回收器准备回收时会被调用。这给了对象在被回收之前做一些清理工作的机会。例如,可以在finalize方法中关闭打开的文件,释放网络连接,释放数据库资源等。

​ 然而,Java规范并未保证垃圾回收时对象的finalize方法一定会被执行。首先,垃圾回收的时间是不确定的,它取决于Java运行时环境的垃圾回收策略和内存压力情况。因此,一个对象在失去引用后到被回收的时间间隔是不确定的。其次,即使垃圾回收器开始回收一个对象,也并不一定会调用这个对象的finalize方法。特别是在finalize方法执行过程中出现异常,那么这个异常也不会被捕获或处理,而是会直接终止finalize方法的执行。

​ 因此,我们在编程时,不应依赖finalize方法来进行资源的清理。而是应该使用finally块或者使用try-with-resources结构来保证资源的正确清理。

​ 此外,值得注意的是,由于finalize方法的执行需要消耗一定的系统资源,并且可能会增加垃圾回收的复杂性和时间,所以Java 9开始,Java规范已经废弃了Object类的finalize方法。在新的Java版本中,推荐使用java.lang.ref.Cleaner或者java.lang.ref.PhantomReference来替代finalize方法,进行对象回收前的清理工作。

​ 总的来说,Java的垃圾回收机制通过回收不再被引用的对象来释放内存,但是并不能保证对象的finalize方法在垃圾回收时一定会被执行。在编程时,我们应避免依赖finalize方法,而应使用更可靠的方式来进行资源的清理。

E. Java是跨平台的语言,无论通过哪个版本的Java编写的程序都能在所有的Java运行平台中运行
F. Java通过synchronized进行访问的同步,synchronized作用非静态成员方法和静态成员方法上的同步的目标是不同的。

​ 在Java中,我们可以使用synchronized关键字来进行线程同步。synchronized可以用于修饰方法和代码块,根据其作用对象的不同,它主要可以分为两种形式:实例锁(即在非静态成员方法上的同步)和全局锁(即在静态成员方法上的同步)。

首先,我们来看一下实例锁。当我们在非静态成员方法上使用synchronized关键字时,就会生成一个实例锁。这种锁是针对每个实例对象的,不同的实例对象之间不会产生互斥关系,只有对同一个实例对象进行操作时,才会发生互斥。这是因为非静态成员方法存在于每个实例对象中,属于实例对象的私有方法,因此每个实例对象都会有一个独立的锁。

再来看全局锁。当我们在静态成员方法上使用synchronized关键字时,就会生成一个全局锁。这种锁是针对类的,无论有多少个实例对象,它们共享同一个全局锁,只要有一个实例对象获取了这个锁,其他实例对象都无法进行相应的操作,必须等待锁被释放。这是因为静态成员方法属于类方法,只存在于类中,不属于任何实例对象,因此所有的实例对象都共享同一个锁。

在Java中,对于synchronized关键字的使用,还需要注意以下几点:

1、synchronized关键字不能继承。也就是说,如果在父类中的某个方法使用了synchronized关键字,那么在子类中重写这个方法时,不会自动具有synchronized关键字,必须显式地在子类中的这个方法上再次添加synchronized关键字。

2、synchronized关键字不能被中断。也就是说,一旦一个线程获取到了某个锁,其他线程只能等待,不能中断它。

3、synchronized关键字必须配合wait()和notify()方法使用,才能实现线程间的通信。wait()方法可以让持有锁的线程进入等待状态,并释放锁;notify()方法可以唤醒一个等待的线程,并让它重新获取锁。

总的来说,synchronized关键字是Java中实现线程同步的一个重要工具,它可以帮助我们解决多线程并发访问共享资源时可能出现的冲突和数据不一致的问题。但在使用时,需要注意其作用范围和特性,合理地选择实例锁或全局锁,以及配合wait()和notify()方法,才能更好地实现线程同步。

0 人点赞