面试

遇到的面试题

接口和抽象类的区别是什么?

Java提供和支持创建抽象类和接口。它们的实现有共同点,不同点在于:

-----接口中所有的方法隐含的都是抽象的。而抽象类则可以同时包含抽象和非抽象的方法;

-----接口中的成员方法默认是public的。抽象类的成员函数可以是private,protected或者是public;

-----接口中声明的变量默认都是final的。抽象类可以包含非final的变量;

-----类可以实现很多个接口,但是只能继承一个抽象类;

----类可以不实现抽象类和接口声明的所有方法,当然,在这种情况下,类也必须得声明成是抽象的;

----抽象类可以在不提供接口方法实现的情况下实现接口;

----接口是绝对抽象的,不可以被实例化。抽象类也不可以被实例化,但是,如果它包含main方法的话是可以被调用的;

## Jsp内置9大对象
page,pagecontext,session,application,request,response,out,exception,config

## 多线程的创建方式

---------继承Thread类 但 Thread 本质上也是实现了 Runnable 接口的一个实例,它代表一个线程的实例,

---------实现 Runnable 接口的方式实现多线程,并且实例化 Thread,传入自己的 Thread 实例,调用 run( )方法

---------使用 ExecutorService、Callable、Future 实现有返回结果的多线程:ExecutorService、Callable、Future这 个 对 象 实 际 上 都 是 属 于 Executor 框 架 中 的 功 能 类 。

synchronized 和 volatile 关键字的作用
一旦一个共享变量(类的成员变量、类的静态成员变量)被 volatile 修饰之后,那么就具备了两层语义:
1)保证了不同线程对这个变量进行操作时的可见性,即一个线程修改了某个变量的值,这新值对其他线程来说是立即可见的。
2)禁止进行指令重排序。
volatile 本质是在告诉 jvm 当前变量在寄存器(工作内存)中的值是不确定的,需要从主存中读取;
synchronized 则是锁定当前变量,只有当前线程可以访问该变量,其他线程被阻塞住。
1.volatile 仅能使用在变量级别;
synchronized 则可以使用在变量、方法、和类级别的
2.volatile 仅能实现变量的修改可见性,并不能保证原子性;
synchronized 则可以保证变量的修改可见性和原子性
3.volatile 不会造成线程的阻塞;
synchronized 可能会造成线程的阻塞。
4.volatile 标记的变量不会被编译器优化;
synchronized 标记的变量可以被编译器优化

什么是线程池,如何使用?
线程池就是事先将多个线程对象放到一个容器中,当使用的时候就不用 new 线程而是直接去池中拿线程即可,节省了开辟子线程的时间,提高的代码执行效率。

合理利用线程池能够带来三个好处。
	第一:降低资源消耗。通过重复利用已创建的线程降低线程创建和销毁造成的消耗。
	第二:提高响应速度。当任务到达时,任务可以不需要等到线程创建就能立即执行。
	第三:提高线程的可管理性。线程是稀缺资源,如果无限制的创建,不仅会消耗系统资源,还会降低系统的稳定性,使用线程池可以进行统一的分配,调优和监控。

重定向和转发的区别

  • 重定向
    跳转后地址栏会发生变化
    页面完全执行完成之后进行跳转
    可以传递session域对象信息
  • 转发
    跳转后地址栏不会发生变化
    执行到转发的代码立刻无条件跳转
    可以传递session及request域对象信息

0,1,1,2,3,5,8,13,21,34…求出第30位的值 使用递归写出

public static int method(int index){
	if(index==0){
		return 0;
	}else if(index==1){
	 	return 1;
	}else{
		return method(index-2)+method(index-1);
	}
}

有两个升序排序好了的数组,他们的长度分别是n,m.并且n>m*m.请求出两个集合的交集以你能想到最小时间复杂度完成。不可用使用Java内部实现的方法。

使用两个指针
哪边小,哪边的指针向右移
相等 两个指针同时向右移
时间复杂度 O(n+m)
也可使用二分法 但时间复杂度更长 O(mlogn)

public static List<Integer> DoublePoint(int[]m,int[]n){
		int pointM=0;   //指针
		int pointN=0;  
		List<Integer> list = new ArrayList<Integer>();
		while(pointM<m.length&&pointN<n.length) {
			if(m[pointM]==n[pointN]) {
				list.add(m[pointM]);
				pointM++;
				pointN++;
			}else if(m[pointM]<n[pointN]) {
				pointM++;
			}else {
				pointN++;
			}
		}
		return list;
	}

基本类型转换分为自动转换和强制转换

  • 自动转换规则:容量小的数据类型可以自动转换成容量大的数据类型,也可以说低级自动向高级转换。这儿的容量指的不是字节数,而是指类型表述的范围。

  • 强制转换规则:高级变为低级需要强制转换。

List 的三个子类的特点

  • ArrayList 底层结构是数组,底层查询快,增删慢。
  • LinkedList 底层结构是链表型的,增删快,查询慢。
  • voctor 底层结构是数组 线程安全的,增删慢,查询慢。

List 和 Map、Set 的区别

-------结构特点

  • List 和 Set 是存储单列数据的集合 。Map 是存储键和值这样的双列数据的集合;

  • List 中存储的数据是有顺序,并且允许重复;

  • Map 中存储的数据是没有顺序的,其键是不能重复的,它的值是可以有重复的

  • Set中存储的数据是无序的,且不允许有重复,但元素在集合中的位置由元素的 hashcode 决定,位置是固定的(Set 集合根据hashcode 来进行数据的存储,所以位置是固定的,但是位置不是用户可以控制的,所以对于用户来说 set 中的元素还是无序的)


-------实现类

  • List 接口有三个实现类(LinkedList:基于链表实现,链表内存是散乱的,每一个元素存储本身内存地址的同时还存储下一个元素的地址。链表增删快,查找慢;ArrayList:基于数组实现,非线程安全的,效率高,便于索引,但不便于插入删除;Vector:基于数组实现,线程安全的,效率低)。

  • Map 接口有三个实现类(HashMap:基于 hash 表的 Map 接口实现,非线程安全,高效,支持 null 值和 null键;HashTable:线程安全,低效,不支持 null 值和 null 键;LinkedHashMap:是 HashMap 的一个子类,保存了记录的插入顺序;SortMap 接口:TreeMap,能够把它保存的记录根据键排序,默认是键值的升序排序)。

  • Set 接口有两个实现类(HashSet:底层是由 HashMap 实现,不允许集合中有重复的值,使用该方式时需要重写 equals()和 hashCode()方法LinkedHashSeWt:继承与 HashSet,同时又基于 LinkedHashMap 来进行实现,底W层使用的是 LinkedHashMp)。
    什么是乐观锁 什么是悲观锁

  • 悲观锁(Pessimistic Lock),
    顾名思义,就是很悲观,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会block直到它拿到锁。传统的关系型数据库里边就用到了很多这种锁机制,比如行锁,表锁等,读锁,写锁等,都是在做操作之前先上锁

  • 乐观锁(Optimistic Lock), 顾名思义,就是很乐观,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,可以使用版本号等机制。乐观锁适用于多读的应用类型,这样可以提高吞吐量,像数据库如果提供类似于write_condition机制的其实都是提供的乐观锁。

  • 两种锁各有优缺点,不可认为一种好于另一种,像乐观锁适用于写比较少的情况下,即冲突真的很少发生的时候,
    这样可以省去了锁的开销,加大了系统的整个吞吐量。但如果经常产生冲突,上层应用会不断的进行retry,这样反倒是降低了性能,
    所以这种情况下用悲观锁就比较合适。

SpringMVC 的工作原理
a. 用户向服务器发送请求,请求被 springMVC 前端控制器 DispatchServlet 捕获;
b. DispatcherServle 对请求 URL 进行解析,得到请求资源标识符(URL),然后根据该 URL 调用 HandlerMapping将请求映射到处理器 HandlerExcutionChain;
c. DispatchServlet 根据获得 Handler 选择一个合适的 HandlerAdapter 适配器处理;
d. Handler 对数据处理完成以后将返回一个 ModelAndView()对象给 DisPatchServlet;
e. Handler 返回的 ModelAndView()只是一个逻辑视图并不是一个正式的视图,
DispatcherSevlet 通过ViewResolver 试图解析器将逻辑视图转化为真正的视图 View;
h. DispatcherServle 通过 model 解析出 ModelAndView()中的参数进行解析最终展现出完整的 view 并返回给客户端;

BeanFactory和ApplicationContext的区别
BeanFactory:是Spring里面最低层的接口,提供了最简单的容器的功能,只提供了实例化对象和拿对象的功能;BeanFactory在启动的时候不会去实例化Bean,中有从容器中拿Bean的时候才会去实例化;
ApplicationContext:应用上下文,继承BeanFactory接口,它是Spring的一各更高级的容器,提供了更多的有用的功能;ApplicationContext在启动的时候就把所有的Bean全部实例化了。它还可以为Bean配置lazy-init=true来让Bean延迟实例化;

	1) 国际化(MessageSource)

	2) 访问资源,如URL和文件(ResourceLoader)

	3) 载入多个(有继承关系)上下文 ,使得每一个上下文都专注于一个特定的层次,比如应用的web层  

	4) 消息发送、响应机制(ApplicationEventPublisher)

	5) AOP(拦截器

fail-fast 和fail-safe的区别
https://blog.youkuaiyun.com/qq_43686443/article/details/84555500

客户端client 突然断电了,那么服务器如何快速的知道呢
(1)使用定时器(适合有数据流动的情况)。
(2)使用socket选项SO_KEEPALIVE(适合没有数据流动的情况)。
心跳包的发送,通常有两种技术:
心跳包技术:心跳包之所以叫心跳包是因为:它像心跳一样每隔固定时间发一次,以此来告诉服务器,这个客户端还活着。事实上这是为了保持长连接,至于这个包的内容,是没有什么特别规定的,不过一般都是很小的包,或者只包含包头的一个空包。

方法1:应用层自己实现的心跳包。

由应用程序自己发送心跳包来检测连接是否正常。大致的方法是:服务器端在一个 定时事件中 定时向客户端发送一个短小的数据包,然后启动一个线程,在该线程当中不断检测客户端的ACK应答包。如果在定时时间内收到了客户端的ACK应答包,说明客户端与服务器端的TCP连接仍然是可用的。但是,如果定时器已经超时、而服务器仍然没有收到客户端的ACK应答包,即可以认为客户端已经断开。同样道理,如果客户端在一定时间内没有收到服务器的心跳包,则也会认为改TCP连接不可用了。

方法2:TCP协议的KeepAlive保活机制。

因为要考虑到一个服务器通常会连接很多个客户端,因此,由用户在应用层自己实现心跳包,代码较多而且稍显复杂。而利用TCP/IP协议层的内置的KeepAlive功能来实现心跳功能则简单得多。不论是服务器端还是客户端,只要一端开启KeepAlive功能后,就会自动的在规定时间内向对端发送心跳包, 而另一端在收到心跳包后就会自动回复,以告诉对端主机我仍然在线。因为开启KeepAlive功能需要消耗额外的宽带和流量,所以TCP协议层默认是不开启KeepAlive功能的。尽管这微不足道,但是在按流量计费的环境下增加了费用,另一方面,KeepAlive设置不合理的话有可能会 因为短暂的网络波动而断开健康的TCP连接。并且,默认的KeepAlive超时需要即2小时,探测次数为5次。对于很多服务端应用程序来说,2小时的空闲时间太长。因此,我们需要手工开启KeepAlive功能并设置合理的KeepAlive参数

drop delete truncate分别在什么场景下使用

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值