1.“equal”、“==” 和 “hashCode” 的区别和使用场景
三者都是用于判断对象之间是否相等的,判断的方式不一样。
==
对于基本类型,==
是比较其值是不是相等,对于引用类型,==
比较两个对象是否相同。
equals方法
equals
方法是用于比较两个独立对象的内容是否相同:
- 如果一个类没有重写 equals(Object obj)方法,则等价于通过 == 比较两个对象,即比较的是对象在内存中的空间地址是否相等。
- 如果重写了equals(Object ibj)方法,则根据重写的方法内容去比较相等,返回 true 则相等,false 则不相等。
hashcode()
hashCode 是用来在散列存储结构中确定对象的存储地址的。hashCode 的存在主要用于查找的快捷性,如 Hashtable, HashMap 等,
- 如果两个对象相同,就是适用于 euqals(java.lang.Object) 方法,那么这两个对象的 hashCode一定相同。
- 如果对象的euqals 方法被重写,那么对象的 hashCode 也尽量重写,并且产生 hashCode 使用的对象,一定要和 equals 方法中使用的一致。
- 两个对象的 hashCode 相同,并不一定表示这两个对象就相同,也就是不一定适用于equals() 方法,只能够说明这两个对象在散列存储结构中,如 Hashtable.,他们存在同一个篮子里。
使用场景:
equals
方法是用于比较两个独立对象的内容是否相同。hashCode方法存在的主要目的就是提高判断效率,如用来在散列存储结构中确定对象的存储地址的。
因为 hashCode
并不是完全可靠,有时候不同的对象他们生成的 hashcode
也会一样(hash冲突),所以 hashCode
只能说是大部分时候可靠,并不是绝对可靠,所以可以得出:
equals
相等的两个对象他们的hashCode
肯定相等,也就是用equals
对比是绝对可靠的hashCode
相等的两个对象他们的equals
不一定相等,也就是hashCode
不是绝对可靠的。
对于需要大量并且快速的对比的话如果都用 equals
去做显然效率太低,解决方式是,每当需要对比的时候,首先用 hashCode
去对比,如果 hashCode
不一样,则表示这两个对象肯定不相等(也就是不必再用 equals
去再对比了),如果 hashCode
相同,此时再对比他们的 equals
,如果 equals
也相同,则表示这两个对象是真的相同了
2.DNS域名解析过程
简略版
浏览器缓存——》系统hosts文件——》本地DNS解析器缓存——》本地域名服务器(本地配置区域资源、本地域名服务器缓存)——》根域名服务器——》主域名服务器——》下一级域名域名服务器
客户端——》本地域名服务器(递归查询)
本地域名服务器—》DNS服务器的交互查询是迭代查询
详细解释
当我们在浏览器地址栏中输入某个Web服务器的域名时。用户主机首先用户主机会首先在自己的DNS高速缓存中查找该域名所应的IP地址。
如果没有找到,则会向网络中的某台DNS服务器查询,DNS服务器中有域名和IP地映射关系的数据库。当DNS服务器收到DNS查询报文后,在其数据库中查询,之后将查询结果发送给用户主机。
现在,用户主机中的浏览器可以通过Web服务器的IP地址对其进行访问了。
如果上级的DNS没有该域名的DNS缓存,则会继续向更上级查询,包含两种查询方式,分别是递归查询和迭代查询。
递归查询
如果主机所询问的本地域名服务器不知道被查询域名的 IP 地址,那么本地域名服务器就以 DNS 客户端的身份,向其他根域名服务器继续发出查询请求报文,即替主机继续查询,而不是让主机自己进行下一步查询。
我们以一个例子来了解DNS递归查询的工作原理,假设图中的主机 (IP地址为m.xyz.com) 想知道域名y.abc.com的IP地址。
- 1、主机首先向其本地域名服务器进行递归查询。
- 2、本地域名服务器收到递归查询的委托后,也采用递归查询的方式向某个根域名服务器查询。
- 3、根域名服务器收到递归查询的委托后,也采用递归查询的方式向某个顶级域名服务器查询。
- 4、顶级域名服务器收到递归查询的委托后,也采用递归查询的方式向某个权限域名服务器查询。
过程如图所示:
迭代查询
当根域名服务器收到本地域名服务器发出的迭代查询请求报文时,要么给出所要查询的IP 地址,要么告诉本地服务器下一步应该找哪个域名服务器进行查询,然后让本地服务器进行后续的查询。
迭代查询过程如下:
- 1、主机首先向其本地域名服务器进行递归查询。
- 2、本地域名服务器采用迭代查询,它先向某个根域名服务器查询。
- 3、根域名服务器告诉本地域名服务器,下一次应查询的顶级域名服务器的IP地址。
- 4、本地域名服务器向顶级域名服务器进行迭代查询。
- 5、顶级域名服务器告诉本地域名服务器,下一次应查询的权限域名服务器的IP地址。
- 6、本地域名服务器向权限域名服务器进行迭代查询。
- 7、权限域名服务器告诉本地域名服务器所查询的域名的IP地址。
- 8、本地域名服务器最后把查询的结果告诉主机。
过程如图所示:
由于递归查询对于被查询的域名服务器负担太大,通常采用以下模式:从请求主机到本地域名服务器的查询是递归查询,而其余的查询是迭代查询。
3.synchronized关键字及加到方法和对象上的区别
Synchronized
是Java
提供的同步关键字,在多线程场景下,对共享资源代码段进行读写操作(必须包含写操作,光读不会有线程安全问题,因为读操作天然具备线程安全特性),可能会出现线程安全问题,我们可以使用Synchronized
锁定共享资源代码段,达到互斥(mutualexclusion
)效果,保证线程安全。
synchronized 既可以加在一段代码上,也可以加在方法上。
加到对象上(加到代码块上)
使用synchronized(object) { 代码块.... } 能对代码块进行加锁,不允许其他线程访问,其的作用原理是:在object内有一个变量,当有线程进入时,判断是否为0,如果为0,表示可进入执行该段代码,同时将该变量设置为1,这时其他线程就不能进入;当执行完这段代码时,再将变量设置为0。
加到方法上
synchronized加在方法上本质上还是等价于加在对象上的。
如果synchronized加在一个类的普通方法上,那么相当于synchronized(this)。
如果synchronized加载一个类的静态方法上,那么相当于synchronized(Class.this)。
4.HTTP/HTTPS区别
HTTP协议传输的数据都是未加密的,也就是明文的,因此使用HTTP协议传输隐私信息非常不安全,为了保证这些隐私数据能加密传输,于是网景公司设计了SSL(Secure Sockets Layer)协议用于对HTTP协议传输的数据进行加密,从而就诞生了HTTPS。为了数据传输的安全,HTTPS在HTTP的基础上加入了SSL/TLS协议,SSL/TLS依靠证书来验证服务器的身份,并为浏览器和服务器之间的通信加密。
HTTPS和HTTP的区别主要如下:
1、https协议需要到ca申请证书,一般免费证书较少,因而需要一定费用。
2、http的信息是明文传输,https则是具有安全性的ssl加密传输协议。
3、http和https使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443。
4、http的连接很简单,是无状态的;HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,比http协议安全。
5.MySQL删除数据的方式都有哪些?/delete/drop/truncate区别、谁的速度更快以及原因
可以这么理解,一本书,delete是把目录撕了,truncate是把书的内容撕下来烧了,drop是把书烧了
常用的三种删除方式:通过 delete、truncate、drop 关键字进行删除;这三种都可以用来删除数据,但场景不同。
执行速度
drop > truncate >> DELETE
区别详解
delete
1、DELETE属于数据库DML操作语言,只删除数据不删除表的结构,会走事务,执行时会触发trigger;
2、在 InnoDB 中,DELETE其实并不会真的把数据删除,mysql 实际上只是给删除的数据打了个标记为已删除,因此 delete 删除表中的数据时,表文件在磁盘上所占空间不会变小,存储空间不会被释放,只是把删除的数据行设置为不可见。虽然未释放磁盘空间,但是下次插入数据的时候,仍然可以重用这部分空间(重用 → 覆盖)。
3、DELETE执行时,会先将所删除数据缓存到rollback segement中,事务commit之后生效;
4、delete from table_name删除表的全部数据,对于MyISAM 会立刻释放磁盘空间,InnoDB 不会释放磁盘空间;
5、对于delete from table_name where xxx 带条件的删除, 不管是InnoDB还是MyISAM都不会释放磁盘空间;
6、delete操作以后使用optimize table table_name会立刻释放磁盘空间。不管是InnoDB还是MyISAM 。所以要想达到释放磁盘空间的目的,delete以后执行optimize table 操作。
7、delete 操作是一行一行执行删除的,并且同时将该行的的删除操作日志记录在redo和undo表空间中以便进行回滚(rollback)和重做操作,生成的大量日志也会占用磁盘空间。
truncate
1、truncate:属于数据库DDL定义语言,不走事务,原数据不放到 rollback segment 中,操作不触发 trigger。
执行后立即生效,无法找回 执行后立即生效,无法找回 执行后立即生效,无法找回
2、truncate table table_name立刻释放磁盘空间 ,不管是 InnoDB和MyISAM。truncate table其实有点类似于drop table 然后creat,只不过这个create table 的过程做了优化,比如表结构文件之前已经有了等等。所以速度上应该是接近drop table的速度;
3、truncate能够快速清空一个表。并且重置auto_increment的值。
小心使用 truncate,尤其没有备份的时候,如果误删除线上的表,记得及时联系中国民航,订票电话:400-806-9553
Drop
1、drop:属于数据库DDL定义语言,同Truncate;
2、drop table table_name 立刻释放磁盘空间 ,不管是 InnoDB 和 MyISAM;drop 语句将删除表的结构被依赖的约束(constrain)、触发器(trigger)、索引(index); 依赖于该表的存储过程/函数将保留,但是变为 invalid 状态。
小心使用 drop ,要删表跑路的兄弟,请在订票成功后在执行操作!订票电话:400-806-9553
6.Linux根目录下有哪些基本目录
/bin:里边包含了一般程序工具,用户、管理员、系统都可以调用。比如常用的ls、cp、cat、mv等等。
/sbin:系统和系统管理员用到的程序工具。
/lib、/lib64:库文件,包含了所有系统和用户需要的程序文件,64表示64位,但实际上除特殊的库,大部分还是链接到了lib目录下。
/home:一般用户目录,一般一个用户对应一个目录,保存用户的数据。
/root:root用户的家目录。
/etc:包含了大部分重要的系统配置文件,这里文件的作用类似windows中的控制面板。
/boot:系统启动文件和内核,在有些发行版中还包括grub,grub是一种通用的启动引导程序。
/dev:系统设备文件目录,除cpu外的所有的硬件设备都会抽象成特殊的文件放在这里,虚拟设备也放在这里。
/media:磁盘设备自动挂载的位置。按照用户分类,每一个用户目录下有其磁盘目录。
/cdrom:专门用来挂载光盘的目录,有些发行版将该目录放在media或mnt目录下。
/mnt:标准挂载点,可以挂载外设磁盘。
/opt:一般存放第三方软件。
/tmp:系统使用的临时空间,重启后会清空。
/var:包含一些用户可变的或临时的文件,比如log文件、邮件队列、网络下载的临时文件等等。
/sys:与proc类似的虚拟文件系统,都是内核提供给用户的接口,可读可写。
/proc:包含系统资源信息的虚拟文件系统,提供了一个接触内核数据的接口,大部分是只读的,有些允许改变。系统运行时才有文件。
7.Java类加载过程
Java类加载过程主要可以分为三个步骤:加载、连接、初始化。
- 加载:是Java将字节码数据从不同的数据源读取到JVM中,映射为JVM认可的数据结构。
连接:是把原始的类定义信息平滑地转入JVM运行的过程中。这一阶段可以细分为验证、准备、解析三步。
验证:
- 1.格式检查 --> 魔数验证、版本检查、长度检查
- 2.语义检查 --> 是否继承final、是否有父类、是否实现抽象方法
- 3.直接验证 --> 跳转指令是否只想正确的位置,操作数类型是否合理
- 4.符号引用验证 --> 符号引用的直接引用是否存在
准备:
- 为类中的所有静态变量分配内存空间,并为其设置一个初始值(由于还没有产生对象,实例变量不在此操作范围内)被final修饰的静态变量, 会直接赋予原值;类字段的字段属性表中存在ConstantValue属性,则在准备阶段,其值就是ConstantValue的值
解析:
- 将常量池中的符号引用转为直接引用(得到类或者字段、方法在内存中的指针或者偏移量,以便直接调用该方法),这个可以在初始化之后 再执行。可以认为是一些静态绑定的会被解析,动态绑定则只会在运行是进行解析;静态绑定包括一些final方法(不可以重写),static方法(只 会属于当前类),构造器(不会被重写)
- 初始化:是执行类初始化的代码逻辑,包括静态字段赋值的动作,以及执行类定义中的静态初始化块内的逻辑。
8.堆和栈的区别
堆和栈的区别主要有五大点,分别是:
1、申请方式的不同。栈由系统自动分配,而堆是人为申请开辟;
2、申请大小的不同。栈获得的空间较小,而堆获得的空间较大;
3、申请效率的不同。栈由系统自动分配,速度较快,而堆一般速度比较慢;
4、存储内容的不同。栈内存存储的是局部变量而堆内存存储的是实体; 栈在函数调用时,函数调用语句的下一条可执行语句的地址第一个进栈,然后函数的各个参数进栈,其中静态变量是不入栈的。而堆一般是在头部用一个字节存放堆的大小,堆中的具体内容是人为安排;
5、底层不同。栈是连续的空间,而堆是不连续的空间。
6、栈内存存放的变量生命周期一旦结束就会被释放,而堆内存存放的实体会被垃圾回收机制不定时的回收。
9.生产者消费者模型
概念
生产者消费者模式就是通过一个容器来解决生产者和消费者的强耦合问题。生产者和消费者彼此之间不直接通讯,而通过阻塞队列来进行通讯,所以生产者生产完数据之后不用等待消费者处理,直接扔给阻塞队列,消费者不找生产者要数据,而是直接从阻塞队列里取,阻塞队列就相当于一个缓冲区,平衡了生产者和消费者的处理能力。这个阻塞队列就是用来给生产者和消费者解耦的。
321原则
三种角色:生产者、消费者、仓库
两种关系:生产者与生产者之间是互斥关系,消费者与消费者之间是互斥关系,生产者与消费者之间是同步与互斥关系。
一个交易场所:仓库
优点
解耦–生产者。消费者之间不直接通信,降低了耦合度。
支持并发
支持忙闲不均
PV原语描述
s1初始值为缓冲区大小、s2初始值为0
生产者:
生产一个产品;
P(s1);
送产品到缓冲区;
V(s2);
消费者:
P(s2);
从缓冲区取出产品;
V(s1);
消费水平;
代码实现
- synchronized + wait() + notify() 方式
package ProducerAndConsumer;
import java.util.ArrayList;
import java.util.List;
class Produce extends Thread {
List<Object> productBuffer; // 产品缓冲区
int bufferCapacity; // 缓冲区容量
public Produce(int bufferCapacity,List<Object> productBuffer){
this.productBuffer = productBuffer;
this.bufferCapacity = bufferCapacity;
}
@Override
public void run() {
while (true){ // 生产行为
synchronized (productBuffer){ // 如果某一个生产者能执行进来,说明此线程具有productBuffer对象的控制权,其它线程(生产者&消费者)都必须等待
if(productBuffer.size()==bufferCapacity){ // 缓冲区满了
try {
productBuffer.wait(1); // 释放控制权并等待
} catch (InterruptedException e) {
e.printStackTrace();
}
}else { // 缓冲区没满可以继续生产
productBuffer.add(new Object());
System.out.println("生产者生产了1件物品,当前缓冲区里还有" + productBuffer.size() + "件物品");
productBuffer.notifyAll(); // 唤醒等待队列中所有线程
}
}
// 模拟生产缓冲时间
try {
Thread.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class Consumer extends Thread{
List<Object> productBuffer; // 产品缓冲区
int bufferCapacity; // 缓冲区容量
public Consumer(int bufferCapacity,List<Object> productBuffer){
this.productBuffer = productBuffer;
this.bufferCapacity = bufferCapacity;
}
@Override
public void run(){
while (true){//消费行为
synchronized (productBuffer){
if(productBuffer.isEmpty()){ //产品缓冲区为空,不能消费,只能等待
try {
productBuffer.wait(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}else { // 缓冲区没空可以继续消费
productBuffer.remove(0);
System.out.println("消费者消费了1个物品,当前缓冲区里还有" + productBuffer.size() + "件物品");
productBuffer.notifyAll();
}
}
// 模拟消费缓冲时间
try {
Thread.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public class ProducerAndConsumer {
public static void main(String[] args) {
List<Object> productBuffer = new ArrayList<>(); // 产品缓冲区
int bufferCapacity = 3; // 缓冲区容量
for (int i = 0; i < 3; i++) {
new Produce(bufferCapacity,productBuffer).start();
}
for (int i = 0; i < 3; i++) {
new Consumer(bufferCapacity,productBuffer).start();
}
}
}
10.servlet是线程安全的吗
Servlet不是线程安全的。
当Tomcat接收到Client的HTTP请求时,Tomcat从线程池中取出一个线程,之后找到该请求对应的Servlet对象并进行初始化,之后调用service()方法。要注意的是每一个Servlet对象再Tomcat容器中只有一个实例对象,即是单例模式。如果多个HTTP请求请求的是同一个Servlet,那么着两个HTTP请求对应的线程将并发调用Servlet的service()方法。
11.http请求头和响应头信息
请求头信息
- Accept:浏览器能够处理的内容类型
- Accept-Charset:浏览器能够显示的字符集
- Accept-Encoding:浏览器能够处理的压缩编码
- Accept-Language:浏览器当前设置的语言
- Connection:浏览器与服务器之间连接的类型
- Cookie:当前页面设置的任何Cookie
- Host:发出请求的页面所在的域
- Referer:发出请求的页面的URL
- User-Agent:浏览器的用户代理字符串
响应头信息
- Date:表示消息发送的时间,时间的描述格式由rfc822定义
- server:服务器名字。
- Connection:浏览器与服务器之间连接的类型
- content-type:表示后面的文档属于什么MIME类型
- Cache-Control:控制HTTP缓存
参考资料
- “equal”、“==” 和 “hashCode” 的区别和使用场景?
- Java 基础 | hashCode 和 equals 在实体类的应用场景
- Java的synchronized加在方法上或者对象上有什么区别?
- 13张图,深入理解Synchronized
- 全网最全JAVA面试八股文,终于整理完了
- 面试官灵魂一问:MySQL 的 delete、truncate、drop 有什么区别?
- Linux根目录下各个目录的介绍
- HTTP与HTTPS的区别
- 多张图带你彻底搞懂DNS域名解析过程
- java 类加载过程(步骤)详解
- 堆和栈的区别有哪些?
- PV操作-生产者/消费者关系
- Java 学习笔记 使用synchronized实现生产者消费者模式
- 经典面试题 -- 手写生产者消费者模式
- Java面试题:Servlet是线程安全的吗?
- http的请求头都有那些信息
评论 (0)