当前位置:   article > 正文

2/12牛客网面试总结_牛客网显示第二轮

牛客网显示第二轮

1.tcp udp区别
TCP面向连接,可靠传输。UDP非连接,不可靠传输。
TCP一对一,UDP一对一,一对多,多对多等。
TCP首部开销20字节,UDP首部开销8字节。所以TCP有超时连接确认重传等机制。更加可靠开销也更大。
TCP面向字节流,UDP面向报文。
TCP适用于可靠性强的场景。UDP适用于实时性高,高速传输场景。
3.浏览器缓存是什么
在这里插入图片描述
所有都有缓存协商,协商这些参数
在这里插入图片描述
1.时效缓存(强制缓存) :Cache-Control
max-age=xxx: 缓存的内容将在 xxx 秒后失效
2.非时效缓存(对比缓存,用的是标识)
Etag (唯一标识)优先级更高
Last-Modified/If-Modified-Since 返回给客户端最后对这个资源的修改时间,优先级没有Etag高
所以
1.失效缓存的优先级更高,如果没失效,就直接用缓存数据库里的东西
2.如果时间已经失效了,就看用的是哪种标识(Etag服务端生成的唯一标识,还是last-modified资源最后修改时间标识)返回304就用缓存里的,返回200就返回body和新的header
3.一般来说,无论如何都会协商缓存,浏览器必备的缓存不可能没有~
4.地址栏输入网址到页面解析
1.浏览器先查看浏览器缓存-系统缓存-路由器缓存,如果缓存中有,会直接在屏幕中显示页面内容。
2.url自动解析成HTTP,
3、需要域名解析(DNS解析),解析获取相应的IP地址。
4、浏览器向服务器发起tcp连接 ,与浏览器建立tcp三次握手。
5、握手成功后,浏览器向服务器发送HTTP请求,请求数据包。
6、服务器处理收到的请求,将数据返回至浏览器
7、浏览器收到HTTP响应
8、读取页面内容,解析html源码,浏览器渲染
9、生成Dom树、解析css样式、js交互
10、客户端和服务器断开连接
6.进程如何通讯
1)首先说说为什么会有进程间通信?
进程与进程之间是相互独立的有独立的虚拟地址空间,所以进程间通信是很难的。但有时候需要两个进程之间实现数据传输、资源共享、通知事件,进程控制 。所以内核给我们提供一份公共资源让两进程都能访问就可以实现通信了
2)方式55555:管道、消息队列、共享内存、信号量、套接字socket。
**管道:**命名管道+匿名管道
Linux下一切皆文件这我们必须牢记,所以管道就是一份文件 。进程A往管道中写数据进程B就可以从另一端读数据了。半双工通信 (当然想要实现全双工通信,只要两个管道就可以了)。面向字节流
匿名管道用pipe()创建,只能用于有亲缘关系的进程间通信。而命名管道则是用于任意进程,也被叫做FIFO文件。
总体来说就是一个进程在管道一边写,另一进程在管道那边读
消息队列:
消息队列就是一个链表 ,进程A可以向队列中写数据(写满则不能写了,因为消息队列是固定的 ),队列中有数据了进程B就可以开始读数据了,读完了数据就不能读了。全双工通信 (只要进程有读写权限就可以双向通信),面向数据报
共享内存:
共享内存就是一块内存 ,内存有随机访问的优势,所以共享内存就成为了进程间通信最快的方式
原理就是 允许两个不相关的进程访问同一个逻辑内存。两个不同的虚拟地址通过页表映射到物理空间的同一区域,它们所指向的这块区域即共享内存。
在这里插入图片描述
但是没有同步机制所以共享内存与信号量一起用
信号量:
信号量准确的来说就没有通信,他可以理解为是一个计数器加上等待队列,因为有时候多个进程同时访问临界资源就会产生死锁,那么就需要信号量记录可申请的资源的数量 ,每申请一次信号量减1,用完释放就加1,等待队列就是资源被申请完了(信号量为0),在申请就会信号量<0,那么此时就会将进程加入等待队列,一旦有资源释放,就可以立马申请到。
信号量的特点就是同步与互斥 !!!
进程控制也是进程间通信的目的之一,那一个进程给另外一个进程发送个9号信号就可以杀死这个进程。
Socket:
与其他通信机制不同的是,它可用于不同机器间的进程通信
那么问题来了进程之间通信为什么不能用全局变量?

1.你要明白全局变量指的是对这个进程所内的内存来说是全局变量的,可见的。其他的进程空间是根本看不到这个变量的 因为他们不属于同一个虚拟内存块 每个进程占用一块独立的虚拟内存块
2.不同进程不能通过全局变量来通信。
同一进程内的线程,他们是可以通过全局变量来通信的。
7.线程间如何通信
之前说了线程同步Synchronized和Lock
线程通信:
111111.wait()/notify()/notifyAll():都是Object方法。
wait():导致当前线程等待并使其进入到等待阻塞状态。直到其他线程调用该同步锁对象的notify()或notifyAll()方法来唤醒此线程。
notify():唤醒在此同步锁对象上等待的单个线程,如果有多个线程都在此同步锁对象上等待,则会任意选择其中某个线程进行唤醒操作,只有当前线程放弃对同步锁对象的锁定,才可能执行被唤醒的线程。
notifyAll():唤醒在此同步锁对象上等待的所有线程,只有当前线程放弃对同步锁对象的锁定,才可能执行被唤醒的线程。
222222.BlockingQueue即阻塞队列,它是基于ReentrantLock(线程安全的)
线程池那边我们也用到了BlockingQueue
BlockingQueue 接口有以下阻塞队列的实现:
FIFO 队列 :LinkedBlockingQueue、ArrayListBlockingQueue(固定长度)
优先级队列 :PriorityBlockingQueue
提供了阻塞的 take() 出列和 put()入列方法:如果队列为空 take() 将一直阻塞到队列中有内容,如果队列为满 put() 将阻塞到队列有空闲位置。它们响应中断,当收到中断请求的时候会抛出 InterruptedException,从而提前结束阻塞状态。阻塞队列的 take() 和 put() 方法是线程安全的。
BlockingQueue还用于消费者与生产者会代码。
8.线程有哪些资源 进程有哪些资源
线程:线程id,程序计数器,一组寄存器和栈
进程:全局变量,静态变量,堆,公共文件等资源
我看你用过Redis 讲一下 Redis的map底层 zset底层
数据库四种隔离级别说一下 分别是干啥的
3.数据库索引有哪些,聚簇索引非聚簇索引区别
9.并行和并发的区别
1.并行:同一时刻可以处理多个任务
2.并发:同一时刻只能处理一个任务,但一个时间段内可以对多个任务交替处理
10.你怎么调优jvm
减少GC的频率和Full GC的次数,过多的GC和Full GC是会占用很多的系统资源(主要是CPU),影响系统的吞吐量。特别要关注Full GC,因为它会对整个堆进行整理,导致Full GC一般由于以下几种情况:
1.老年代空间不足
  调优时尽量让对象在新生代GC时被回收、让对象在新生代多存活一段时间和不要创建过大的对象及数组避免直接在旧生代创建对象
2.永久代空间不足
  增大Perm Gen空间,避免太多静态对象
3.System.gc()被显示调用
  垃圾回收不要手动触发,尽量依靠JVM自身的机制
11.hashmap构造函数参数为10,当到加到11个的时候会怎样
增加第8个元素的时候会扩容到20,第11个元素会正常添加。
12.怎么查看线程死锁
死锁的4444个条件:互斥,持有并等待,不可抢占,循环等待。
死锁预防打破之一条件即可:
1.以确定的顺序获锁
2.超时放弃
怎么查看死锁:
打开cmd
jps获得当前Java虚拟机进程的pid
jstack pid号打印堆栈。内容的最后其实已经报告发现了一个死锁
13.怎么查看线程死循环
和上面一样。
根据打印出的堆栈内容,看看线程们停在哪一行了
14.i++线程不安全原因
i++和++i都是i=i+1的意思,但是过程有些许区别:
i++:先赋值再自加。++i:先自加再赋值。
i++和++i的线程安全分为两种情况:
1、如果i是局部变量(在方法里定义的),那么是线程安全的。因为别的线程访问不到。
2、如果i是全局变量(类的成员变量),那么是线程不安全的。因为如果是全局变量的话,同一进程中的不同线程都有可能访问到
如果有大量线程同时执行i++操作,i变量的副本拷贝到每个线程的工作内存,当同时有两个线程栈以上的线程读取线程变量,假如此时是1的话,那么同时执行i++操作,再写入主内存,最后两个线程执行完,i会等于2而不是3。因为还没来得及刷入主存更新。非原子性导致的!!!!
这个会编译成i = i +1,其实是做了3个步骤,一个是读取,修改,写入 。所以会出现多线程访问冲突问题
15.volatile实现原理
这个关键字汇编语言下编译出lock前缀指令,底层实现是通过插入内存屏障(内存栅栏)
1.禁止重排序,不会把栅栏后的放到栅栏前。
2.强制将修改操作写入主内存
3.写操作,令其他cpu对应缓存行无效,必须重新从主内存拷贝刷新到工作内存。
16.volitle 的应用场景
要使 volatile 变量提供理想的线程安全,必须同时满足下面两个条件:
对变量的写操作不依赖于当前值(i=i+1就不行啊)
该变量没有包含在具有其他变量的不变式中。
所以:可以被写入 volatile 变量的这些有效值独立于任何程序的状态,包括变量的当前状态。
场景:
1.标志状态
volatile boolean flag
2.一次性发布
在缺乏同步的情况下,可能会遇到某个对象引用的更新值(由另一个线程写入)和该对象状态的旧值同时存在。这就是造成双重检查锁定问题的根源。
单例模式:如果不用volatile,可能导致失败。——某个线程可能会获得一个未完全初始化的实例。
public class Singlaeton{
private volatile static Singleton instance =null;
private Singleton(){
}
public static Singleton getInstance(){
if (instancenull){
snchronized(Singleton.class){
if(instance
null)
{instance=new Singleton()
}
}
}

}
}

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/笔触狂放9/article/detail/774648
推荐阅读
相关标签
  

闽ICP备14008679号