<
常见问题
>
上一篇

JavaScript相关
下一篇

shiro权限框架

一、容器相关

1. HashMap 的源码、实现原理、JDK8中对HashMap 的优化。

2. HashMap的扩容机制。

3. HashMap、HashTable、ConcurrentHashMap 的区别。

4. 极高并发下HashTable 和 ConcurrentHashMap 的性能比较及理由。

5. ArrayList 和 LinkedList 的区别、数组、链表和双向链表的了解。

6. ArrayList在循环过程中删除元素会不会出问题?为什么?

7. HashMap 和 TreeMap 的区别。

8. 谈谈你对并发容器的理解。

二、 Java 基础

1. Java 中作用域修饰符
	作用域		     当前类	同一个package	子孙类	其他package

	public		     1		  1				1		1

	protected		 1		  1				1		0

	friendly		 1		  1				0		0

	private 		 1		  0				0		0
2. 抽象类和接口的区别。 3. 构造器 Constructor 能否被重写、能否被重载。
构造方法只能呗重载,不能被重写,不能被继承
4. == 和 equals 的区别、为什么要重写 hashcode。
(1)== 比较的是两个对象内存的引用(即内存地址)是否相等

(2)equals判断的只是对象的值是否相等

(3)成对重写,重写hashcode,必须重写equals。并且需要保持一致性,hashcode的值相等,equals必须相等,反之亦然。否则使用hashmap,可能会效率低下。
5. String 和 StringBuffer 的区别。
(1)string是不可变性,追加的时候会产生很多中间对象

(2)StringBuffer:可变,追加的时候不会产生中间对象,但是线程安全,开销大

(3)StringBuilder:可变,追加的时候不会产生中间对象,但是线程不安全,开销小

一般来说,操作字符串不需要线程安全,所以使用StringBuilder即可。解析http字符串需要线程安全。
6. Object 类中的方法。
(1)hashcode、equals、toString、wait、notify、notifyAll、clone、registerNatives、getClass、finalize
7. Java 序列化的方式。
(1)方式:实现java.io.Serializable接口或者实现Externlizable接口,后者继承前者,并新增了两个方法,可以定义哪些属性序列化,哪些不必序列化。

(2)原因:将对象转化成二进制,用于保存或者网络传输。
8. 动态代理的两种方式,以及区别。
(1)jdk动态代理:通过实现接口的方式

(2)cglib动态代理:通过继承父类的方式

补充:动态代理和静态代理的区别:

9. 值传递和引用传递的区别,Java 中是怎么样的?有没有引用传递?

(1)值传递: 在方法调用过程中,把实际的参数传给形参,相当于复制一份实参的值传递给形参,

如果形参的值改变了,原来的实参值不会改变。除非方法有返回值,覆盖了之前的值。

(2)引用传递:在方法调用的时候,实参传给形参,传的是实参的引用地址,所以形参的值改变了,

实参的值也改变了,因为二者指向同一个地址。

(3)java中是值传递,不管是基本类型还是引用类型都是按照值传递的。

引用类型的值传递,传递的是引用对象在堆中的地址的拷贝,所以如果形参改变,实参也会改变,因为二者指向同一个地址;

基本类型的值传递,传递的是面值的拷贝,二者是不同的,所以形参改变,实参并不改变。
10. TCP 和 UDP 的区别?

都是OSI模型中的传输层

tcp:tcp传输较安全,提供可靠的通信传输

udp:传输不如tcp安全,但比tcp传输快

11. Java 中如何处理跨域访问。

由于浏览器的同源策略(同源:指的是域名、协议、端口都相等)导致了跨域请求问题。

jsonp:将请求地址写到script标签里,因为浏览器同源策略不检测script的静态资源请求
Nginx代理
CORS
12. session 和 cookie 的区别。
常用的会话技术是:session和cookied,记录用户从登录网址到浏览购买的一系列操作,session在服务器端记录,cookie在客户端记录。

session:(1)存储在服务器 (2)安全(3)可以存储一些登录信息

cookie:(1)存储在客户端(2)不安全(3)存储数据类型少,存储的东西不多

应用场景:登录一个网站之后,第二天自动登录了,这是由于cookie的原因,记住密码了。

购物车可以添加到session中,前后端都需要购物车的数量情况,需要保存。
13. 如何防止表单重复提交。
恶意提交表单,刷新页面或者使用postman提交,提交重复数据,增加服务器的负载,严重可能会宕机

(1)使用js禁用button,不推荐(可以刷新页面绕过,或者使用postman);

(2)数据库字段(用户名、电话、邮箱等)增加唯一约束,服务器及时捕捉插入数据异常;

(3)在页面打开时,从后台传个subtoken存到隐藏域中,并且在session里面也保存该标记subToken,每次提交表单把这个subToken带上,

如果没有或者重复就不通过,否则处理该数据,处理完毕清空session
14. JDK新版本更新的新特性的了解。

三、多线程相关

1. Java实现多线程有哪几种方式。
三种:继承Thread、实现Callable、实现Runnable接口
2. Callable 和 Future 的了解。
通过f.get()方法,可以获取线程的返回值,但是如何线程还没执行完,会一直阻塞,直到得到返回结果
   public static void main(String [] args){
		 CallableThread callableThread = new CallableThread();
		 for(int i = 0;i<10;i++){
			 FutureTask f = new FutureTask<Callable>(callableThread);
			 new Thread(f).start();
			 try {
				 Integer a = (Integer) f.get();
				 //获取子线程返回的值
				 System.out.println("子线程返回值a:"+a);
			 } catch (Exception e) {
				 e.printStackTrace();
			 }
		 }
	 }


	 public class CallableThread implements Callable{
		 int i = 1;
		 @Override
		 public Object call() throws Exception {
			 System.out.println("this is callable"+Thread.currentThread().getName());
			 return i++;
		 }
	 }
3. 线程池的参数有哪些?在线程池中创建一个线程的流程。
线程池有七个参数:

(1)corePollSize:核心线程数

	核心线程会一直存活,即使没有任务执行。当线程数小于核心线程数,即使有空闲线程,也会优先创建新线程进行处理。

(2)maximumPoolSize:最大线程数。表明线程中最多能创建的线程数。

	当前线程数 >= corePollSize ,且任务队列已满时,系统会创建新的线程去执行新任务

	当前线程数 = maximumPoolSize ,且任务队列已满时,线程池会拒绝处理任务并抛异常

(3)keepAliveTime:空闲线程保存的时间。

	空闲时间达到keepAliveTime时,线程会退出,直到线程数等于corePollSize

(4)TimeUnit:空闲线程保留的时间单位。

(5)BlockingQueue<Runnable>:阻塞队列(又叫任务队列容量),存储等待执行的任务。

(6)ThreadFactory:线程工厂,用于创建线程。

(7)RejectedExecutionHandler:队列已满,而且任务量大于最大线程的异常存储策略,任务拒绝处理器。

当线程数达到maximumPoolSize,且队列已满,会拒绝新任务。

当线程池调用shutdown,和真正调用shutdown之间,提交的任务会拒绝。
4. volatile 关键字的作用,原理。

修饰变量,当此变量发生改动时,其他线程会知晓。变量不会被缓存到寄存器上或者其他处理器不可见的地方,因此每次读取volatile修饰的变量(都是从内存中读取),返回的都是最新值。

volatile修饰的变量不具有原子性,具有可见性和有序性。

5. synchronized 关键字的用法、优缺点。

可以修饰代码块、方法、类。

不能判断是否获取锁,如果发生异常,会自动释放锁。

synchronized与volatile的区别: 6. Lock接口有哪些实现类,以及使用场景。

(1)Lock接口实现类一共有三个:

ReentrantLock和ReentrantReadWriteLock类里面的两个静态内部类:WriteLock和ReadLock

lock可以修饰代码块,使用unclock释放锁。若发生异常,并且没有使用unclock释放锁(在finally里面释放),会造成阻塞

7. 可重入锁(ReentrantLock)的用处及实现原理。

(1)可重入锁原理:可以重复进入的锁。加锁时会判断,锁是否已经被获取了。如果是,判断是否是当前线程获取的。如果是,那么获取锁的次数加1,否则需要等待。

释放锁时,会给获取锁的次数减1,如果次数是0时,需要调用锁的唤醒方法,让其他被锁上的阻塞线程得到执行机会。

(2)在java环境下,ReentrantLock和Synchronized都是可重入锁。在一个类中,如果Synchronized方法1调用了Synchronized方法2,那么Synchronized方法2会正常执行。

若不然,方法2想获取锁时,该锁已经在方法1执行时获取到了,方法2一直获取不到锁资源,就一直得不到执行。

(3)用处:线程需要多次进入临界区时,会需要用到可重入锁。如:Synchronized方法1,想要调用另一个Synchronized方法时。

(4)可重入锁(可重入锁)可以指定是公平锁还是非公平锁。Synchronized只能是非公平锁。

补充:公平锁:按照等待时间长短,等待时间长优先获取锁。非公平锁:按照优先级判断,优先级越高,越先获取锁。

8. 悲观锁、乐观锁的优缺点。

(1)乐观锁:乐观锁一般会使用版本号机制或CAS算法实现。

ABA,如果一个变量开始的值是A,后来变成B,后来又变成A,这时CAS操作不认为这个变量值被改变过;

自旋时间长(如果不成功就一直循环执行,直到执行成功),开销大;

(2)悲观锁

9.CAS的理解、有什么缺陷?该怎么解决?

CAS算法:比较并交换(Compare-and-Swap,CAS)

CSA有三个操作数,内存地址V,旧的预期值A,新值B。当执行操作时,只有当V等于A时,才把V的值更新为B。

补充:关于synchronized和CAS比较,

10. A、B、C 三个线程如何保证顺序执行。
(1)使用join方法,(join方法:如果在线程a中调用线程b.join(),线程a会一直等待,直到线程b执行结束时,线程a才会执行)

join():参数,如果是10,线程a会等待10毫秒,让线程b执行,10毫秒结束之后,线程a、b并行执行。注意:参数为0,和没有参数一样,线程a一直等待线程b结束之后,再执行。

该方法主要作用就是同步,使线程之间的并行执行改成串行执行。

调用join方法之前必须调用start方法,因为执行完start方法,线程才开始创建。如果线程都没开启,自然也不能同步。

join方法原理:相当于在a线程中,调用了b线程的wait方法,使a线程进行等待,当b线程执行完成时(或到达等待时间),再调用b线程的notifyall方法,唤醒a线程,之后a线程再继续执行

(2)使用单个线程池(newSingleThreadExecutor)方法:这个线程处理完,接着处理下一个线程,发生异常时,将会有新的线程代替。
	public class ThreadTest {
		public static void main(String [] args){
			Thread t1 = new Thread(new Runnable() {
				@Override
				public void run() {
					System.out.println("t1...");
				}
			},"T1");
			Thread t2 = new Thread(new Runnable() {
				@Override
				public void run() {
					try {
						t1.join();
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					System.out.println("t2...");
				}
			},"T2");
			Thread t3 = new Thread(new Runnable() {
				@Override
				public void run() {
					try {
						t2.join();
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					System.out.println("t3...");
				}
			},"T3");
			//方法1:使用join方法
			t3.start();
			t2.start();
			t1.start();
			//方法2:使用线程池的newSingleThreadExecutor方法
	//        ExecutorService executorService = Executors.newSingleThreadExecutor();
	//        executorService.submit(t1);
	//        executorService.submit(t2);
	//        executorService.submit(t3);
	//        executorService.shutdown();
		}

11 线程的状态有哪些?.
	(1)未开始的

	(2)正在运行的

	(3)阻塞的

	(4)永久等待的

	(5)等待一定时间的

	(6)运行结束的
12. sleep 和 wait 的区别。
sleep 方法,不释放锁,定时会自己唤醒。方法是由Thread提供的。

wait方法释放锁资源,需要使用notify(唤醒一个线程)或者notifyall 唤醒所有线程。是由Object类提供的。
13. notify 和 notifyall 的区别。 14. ThreadLocal 的了解,实现原理。
(1)ThreadLocal叫做线程本地变量或者线程本地存储,为变量在每个副本中都创建一个副本,使每个线程都可以访问自己的变量副本,互相不冲突。

  线程安全,但是资源消耗可能会比较大。

(2)ThreadLocal提供的几个方法:每个threadlocal 只能存储一个变量副本,如果想要一个线程有多个变量副本,则需要创建多个Threadlocal。

	public T get() { } //获取ThreadLocal在当前线程中保存的变量副本

	public void set(T value) { }//设置当前线程中的变量副本

	public void remove() { }//移除当前线程中的变量副本

	protected T initialValue() { }//protected类型,一般用于在使用是重写的,延迟加载的方法

(3)应用场景:解决数据库连接和session连接等

四、框架相关

1. SpringMVC执行流程。

如图: image

2. ElasticSearch 的底层原理。 3. Mybatis 如何找到指定的 Mapper的。 4. Spring 的 IoC 有哪些优势。

(1)IoC(Inversion of Control)是控制反转,由IoC容器去创建对象,并且注入依赖对象。

(2)传统方式是在类内主动创建需要依赖的对象,耦合度较高;

而有了IOC之后,创建和查找依赖对象以及对象销毁的控制权交给了spring的IOC容器,耦合性较低,增加程序的复用性和灵活性。

(3)IoC主要分为两个阶段:容器启动阶段和bean实例化阶段。

A.依赖注入方式:

B.Spring提供了两种IoC容器:ApplicationContext是BeanFactory的子类,二者是继承关系。

会加载所有管理的对象并且全部初始化并绑定完成。所以相对BeanFactory来说,ApplicationContext需要更多的系统资源,启动也较之稍微慢一些。

C.通知容器关于关于依赖对象的信息方式:通常使用xml文件方式和注解方式。

5. Spring IOC 和 AOP 原理。

Ioc(控制反转)和DI(依赖注入)是同一个概念的不同描述。

IOC原理:IOC最基本的技术就是反射(根据给出的类名,动态的生成对象机制的工厂模式。一个类注入另一个类对象并不需要自己生成,Ioc会代替这个类生成需要注入的对象。

AOP原理:面向切面编程。主要用于事务管理、日志、缓存、安全机制等。

6. Spring Bean 的生命周期。 7. SpringMVC 的 Controller 是如何将参数和前端的数据一一对应的。

五、数据结构和算法相关

1. 八大排序基本思想及其 Java 语言实现(快排和堆排序重要)。

(1)快速排序:

2. 三大查找算法基本思想和 Java 语言实现。 3. 栈、队列、链表、树基本数据结构及 Java 语言实现。 4. B、B+树的原理。 5. 一致性 Hash 算法,及其应用。 6.java为什么要实现序列化。

序列化是把javabean转换成字节流,可以进行网络传输,

使用场景:把实体类保存到数据库;写文件需要实现序列化;远程调用

远程调用时,会把对象序列化,然后传输给另一个项目,然后另一个项目对这个对象进行反序列化

六、设计模式相关

  1. 常见的设计模式的基本思想、Java 实现、应用场景。

七、 数据库

  1. 事务、锁、索引原理和各种优化。

  2. 数据库事务隔离级别。

原子性、一致性、隔离性、持久性(ACID)

  1. mysql 主从复制的原理

  2. 分库分表:非分表主键跨库查询、跨库分页、分页查询优化。

  3. SQL优化的常见方法有哪些?

八、JVM 调优

  1. 垃圾回收原理和优缺点。

  2. 各种 GC 原理区别、如何确定那些对象应该回收方法。

  3. JVM 的内存结构

  4. Java 类的加载过程。

(1)

(2)类加载过程是指:jvm把字节码文件加载并进内存,并解析生成对应的class对象的过程。

  1. 双亲委派模型的过程以及优势。

不会重复加载类

  1. 常用 JVM 调优参数

九、Linux

  1. 常用的 Linux 命令以及参数。

  2. Vim

Top
Foot