常见Java笔面试题集(二)

常见Java笔面试题集(二)
1.进程与线程的区别
答:进程是执行着的应用程序,而线程是进程内部的一个执行序列。一个应用程序至少一个进程,一个进程至少一个线程。
同一进程的线程共享本进程的地址空间,而进程之间是独立的。同一进程的线程共享本进程的资源,而进程之间的资源是独立的。
2.概括解释线程的几种可用状态
答:

  1. 新建状态new:新创建一个线程对象。
  2. 就绪状态runnable:线程对象创建完成后,其他线程调用该对象的start()方法。该状态的线程位于就绪线程池中,等待被线程调度选中,获取CPU的使用权。
  3. 运行状态running:就绪状态的线性对象获取CPU的时间片,执行程序代码。
  4. 阻塞状态blocked:阻塞状态是线程因为某种原因放弃CPU使用权,暂时停止运行。直到线程进入就绪状态,才有机会获取CPU时间片转到运行状态。
    (1)等待阻塞:运行的线程执行o.wait()方法,该线程会释放占用的所有资源,JVM会把该线程放入“等待池”中。进入这个状态后,是不能自动唤醒的,必须依靠其他线程调用notify()或notifyAll()方法才能被唤醒。
    (2)同步阻塞:运行的线程在获取对象的同步锁时,若该同步锁被其他线程占用,则JVM会把该线程放回到“锁池”中。
    (3)其他阻塞:运行的线程执行sleep()或者join()方法,或者发出I/O请求时,JVM会把该线程置为阻塞状态,当sleep()方法超时、join()方法等待线程终止或者超时、或I/O请求处理完毕时,线程重新转入到就绪状态。
  5. 死亡状态dead:run()、main()方法执行结束,或者因为异常退出run()方法,则该线程生命周期结束。死亡状态线程不可再次复生。

3.什么是死锁?产生死锁的条件是什么?
答:两个或两个以上的线程互相持有对方所需要的资源,都在等待对方执行完毕后才能继续往下执行,结果这些线程处于无限等待中,这时就会产生死锁。
产生条件:
(1).互斥条件:在一段时间内某资源只由一个进程占用。如果此时还有其它进程请求资源,则请求者只能等待,直至占有资源的进程用毕释放。
(2).请求与保持:一个进程因请求被占用资源而发生阻塞时,对已获得的资源保持不放。
(3).不剥夺条件:进程占用的任何资源在没有被释放之前,任何其他进程都无法对他剥夺占用 。
(4).循环等待:当发生死锁时,所等待的进程会形成一个环路,造成永久阻塞。
死锁的原因是:系统资源不足,进程运行推进的顺序不合适,资源分配不当。
4.JVM垃圾回收算法(GC)

  1. 标记–清除算法:1.标记所有需要清楚的对象,2.标记完成后清楚被标记的对象。其标记的过程就是判断对象的有效性,执行的可达性分析的过程。
    缺点:每次进行垃圾回收的同时,会暂停当前用户程序的运行,垃圾回收器需要间隔性的检查,且标记和清除的过程较慢,标记清除后会产生大量的内存碎片,若内存空间不够大时,还需要再一次的垃圾回收。

  2. 标记–复制算法:复制存储算法通过采用双区域交替使用的方式,将内存空间划分为两个等量的区域,每次使用一块,将存活对象复制到另一块区域,原来区域被重置。
    缺点:会暂停当前用户程序的运行,空间利用率降低。

  3. 标记–整理算法:让所有存活对象都向另外一端移动,然后清除掉端边界以外的内存。
    缺点:非实时性的回收,也会暂停用户程序

  4. 分代收集算法:新生代,老年代,永久代,根据不同年代的特点采用适当的垃圾回收算法。

5.简单解释下垃圾回收过程
JVM垃圾回收机制最基本的做法是分代回收,内存的区域被划分为不同的世代,对象根据其存活时间被存放在对应的区域中。内存的分配是发生在新生代中,当一个对象存活时间久了,就会被复制到老年代中,对于不同的年代采用不同的垃圾回收算法。
6.JVM的内存分配
答:基本数据类型变量和对象引用都是在栈上分配的;堆内存用来存放由new创建出的对象和数组;类变量由static修饰的变量,在程序被加载的时就在堆中为类变量分配内存,堆中的内存地址存在栈中;实例变量:new的时候,系统在堆中开辟一块空间分配给变量;局部变量:执行到某方法或某代码时,在栈中开辟内存,当局部变量脱离作用域,就会立即释放。
7.如何解决线程安全问题?
答:基本上所有的并发模式在解决线程安全问题上,都采用“序列化访问临界资源”的方案,即在同一时刻,只能有一个线程访问临界资源,也称同步互斥访问。通常来说,是在访问临界资源的代码前面加上互斥锁,当访问完临界资源后释放锁,让其他线程继续访问。
8.Java中垃圾回收的目的以及什么时候进行垃圾回收?
答:垃圾回收的目的是识别并且丢弃应用中不再使用的对象来释放和重用资源。当对象对当前使用这个对象的程序变得不可触及的时候(可达性分析),该对象就要进行回收了,回收的时间是由JVM决定的。
9.在监视器内部,是如何做线程同步的?
答:监视器和锁在Java虚拟机中是一块使用的,监视器监视一块同步代码块,确保一次只有一个线程执行同步代码块。每一个监视器都和一个对象引用相关联。线程在获取锁之前不允许执行同步代码。
10.创建线程的方式
(1)继承Thread类进行创建

public class MyThread extend Thread{
	public void run(){
		//重写run()方法;
	}
}
public class Main{
	public static void main(String[] args){
		new MyThread().start();  //创建并启动线程
	}
}

(2)实现Runnable接口进行创建

public class MyRunnable implements Runnable{
	public void run(){
		//重写run()方法;
	}
}
public class Main{
	public static void mian(String[] args){
		MyRunnable myrun = new MyRunnable();  //创建线程
		Thread thread = new Thread(myrun);
		thread.start();   //启动线程
	}
}

猜你喜欢

转载自blog.csdn.net/m0_37862403/article/details/89096646