c++ 单例模式_Java面试题总结之设计模式、网络基础、常用算法

2d005ab7a3409a731c774a49e2b35c91.png

一.设计模式

1.单例模式

A.懒汉式

  • 单例模式最简单的实现发现,但是不支持多线程,线程不安全
  • 如果想线程安全,在方法上加上synchronized就可以,不过这样效率低下,99%情况都不会用到
public class Singleton { private static Singleton instance; public static Singleton getInstance(){ if(instance==null){ instance = new Singleton(); } return instance; } private Singleton() { } }

B.饿汉式

线程安全,没有加锁所以效率高,但是类一加载就初始化,浪费内存

public class Singleton { private static Singleton instance = new Singleton(); public static Singleton getInstance(){ return instance; } private Singleton() { }}

C.双重锁

安全且在多线程情况下能保持高性能

public class Singleton { private volatile static Singleton instance; public static Singleton getInstance(){ if(instance==null){ synchronized (Singleton.class){ if(instance==null){ instance = new Singleton(); } } } return instance; } private Singleton() { }}

为什么加双重验证?

因为如果只有第一重验证,线程A,B都通过第一重验证,无论线程A,B哪个获取到了锁对象,对对象进行实例化,释放锁之后,另外一个线程也获取锁对象,也对对象进行实例化,此时,对象就不是单例的了。所以要加双重验证

为什么用要volatile修饰?

volatile主要是保证有序性,禁止重排序的,重排序是指编译器和处理器为了优化程序性能而对指令序列进行重新排序的一种手段,在创建对象的时候,也就是new对象的时候,是有三步的,分别是:

1.分配对象内存空间

2.初始化对象

3.设置instance指向刚分配的内存地址

不用volatile禁止重排序,顺序就可能会变成

1.分配对象内存空间

2.最后才初始化对象

当线程A获取锁因为重排序执行顺序变成1,3,2时,执行到3后instance就不为null了,如果此时线程B判断instance!=null,就直接返回了一个没有初始化的对象了,这样线程B有可能会造成程序崩溃

3.设置instance指向刚分配的内存地址(此时对象还未初始化)

2.工厂模式

  • 步骤:创建一个接口和实现几个接口的实体类,再定义工厂类,之后就可以编写测试类了,相较于抽象工厂模式简单点

Color

public interface Color { void draw();}

Green

public class Green implements Color { @Override public void draw() { System.out.println("Green..."); }}

Yellow

public class Yellow implements Color { @Override public void draw() { System.out.println("Yellow..."); }}

Red

public class Red implements Color { @Override public void draw() { System.out.println("Red..."); }}

ColorFactory

public class ColorFactory { public Color getColor(String type){ if(type==null){ return null; } else if(type.equalsIgnoreCase("Yellow")){ return new Yellow(); }else if(type.equalsIgnoreCase("Red")){ return new Red(); }else if(type.equalsIgnoreCase("Green")){ return new Green(); } return null; }}

测试类

public class ColorFactoryDemo { public static void main(String[] args) { ColorFactory factory = new ColorFactory(); Color yellow = factory.getColor("yellow"); yellow.draw(); }}

3.抽象工厂模式

  • 相较于工厂模式,较为复杂点
  • 步骤:定义多个接口以及接口的实现类,编写抽象工厂类,再编写工厂类,工厂类都是扩展于抽象工厂类,然后再创建一个工厂生成器,之后就可以编写测试类了

shape

public interface Shape { void draw();}

Color

public interface Color { void fill();}

Red

public class Red implements Color { @Override public void fill() { System.out.println("Red..."); }}

Rectangle

public class Rectangle implements Shape { @Override public void draw() { System.out.println("Rectangle..."); }}

AbstractFactory

public abstract class AbstractFactory { public abstract Shape getShape(String type); public abstract Color getColor(String type);}

ColorFactory

public class ColorFactory extends AbstractFactory { @Override public Shape getShape(String type) { return null; } @Override public Color getColor(String type) { if(type==null){ return null; }else if(type.equalsIgnoreCase("Red")){ return new Red(); }else if(type.equalsIgnoreCase("Green")){ return new Green(); }else if(type.equalsIgnoreCase("Yellow")){ return new Yellow(); } return null; }}

ShapeFactory

public class ShapeFactory extends AbstractFactory { @Override public Shape getShape(String type) { if(type==null){ return null; }else if(type.equalsIgnoreCase("Square")){ return new Square(); }else if(type.equalsIgnoreCase("Circle")){ return new Circle(); }else if(type.equalsIgnoreCase("Rectangle")){ return new Rectangle(); } return null; } @Override public Color getColor(String type) { return null; }}

FactoryProduct

public class FactoryProduct { public static AbstractFactory getFactory(String factoryname){ if(factoryname.equalsIgnoreCase("Shape")){ return new ShapeFactory(); }else if(factoryname.equalsIgnoreCase("Color")){ return new ColorFactory(); } return null; }}

测试类

public class AbstractFactoryDemo { public static void main(String[] args) { AbstractFactory shapeFactory = FactoryProduct.getFactory("Shape"); Shape rectangle = shapeFactory.getShape("Rectangle"); rectangle.draw(); AbstractFactory colorFactory = FactoryProduct.getFactory("Color"); Color red = colorFactory.getColor("Red"); red.fill(); }}

二.网络基础

1.OSI七层模式从下到上哪七层

物理层、数据链路层、网络层、传输层、会话层、表示层、应用层

2.TCP协议、ip协议、Http协议分别在哪一层

  • 传输层(tcp、udp协议)
  • 网络层(ip协议)
  • 应用层(Http协议)

3.TCP协议的3次握手过程

b7346ef89e14fd23f9a152447c4a5498.png
  • 第一次握手:客户端给服务器发送一个SYN报文
  • 第二次握手:服务端收到客户端发送的SYN报文,会回应一个SYN+ACK报文
  • 第三次握手:客户端收到SYN+ACK报文后,会回应一个ACK报文

服务端收到ACK报文后,三次握手建立完成,三次握手目的就是为了建立可靠的通信信道

4.TCP协议的4次挥手过程

bd7e37b979253a139fba1d07fbefe957.png
  • 假如是客户端先发起关闭请求
  • 第一次挥手:客户端发送一个FIN报文,报文会指定一个序列号
  • 第二次挥手:服务端收到FIN报文,会发送一个ACK报文,且把从客户端接收到的序列号+1作为ACK报文的序列号,表明收到了客户端的报文
  • 第三次挥手:如果服务端也想断开连接,和客户端第一次挥手一样,发送FIN报文,且指定一个序列号
  • 第四次挥手:客户端收到FIN报文后,一样发送一个ACK报文作为应答,且把从服务端接收到的序列号+1作为自己ACK报文的序列号
  • 服务端收到ACK报文后,就处于关闭状态了

5.TCP和UDP区别

  • TCP面向连接 UDP面向无连接的
  • TCP传输可靠 UDP传输不可靠
  • TCP传输速度慢 UDP传输速度快
  • TCP偏重量级 UDP偏轻量级
  • TCP面向字节流 UD面向报文(数据包)

6.http请求状态码

  • 200 成功
  • 302 重定向
  • 404 请求资源不存在
  • 4xx 客户端错误
  • 5xx 服务端错误

7.http和https区别

  • http是明文传输,https是加密的安全传输
  • http端口是80,https端口是443

8.简述浏览器第一次访问网页情况

浏览器A在第一次请求服务器B的时候,服务器B会在服务端创建一个session,并为该浏览器A创建一个Cookie,并在响应时候把这个Cookie一同返回给浏览器A,这样A在请求数据不变的情况下再次请求服务器B的时候会带着这个Cookie,cookie中包含了sessionid,与服务端的session对应

9.cookie和session区别

  • 两者都是为了解决http协议无状态的情况
  • cookie是存放在浏览器上的,session放在服务器上的
  • session依赖sessionid,而sessionid是存在cookie中的
  • cookie放在本地,别人可以分析存放在本地的cookie进行cookie欺骗,所以安全性不如cookie
  • 单个cookie保存数据不能超过4k,很多浏览器都限制一个站点最多保存20个cookie

10.get和post区别

  • get请求在URL中传送参数有长度限制,post则没有
  • get请求参数在URL可见,post请求参数不可见
  • 从可见性上来看,post请求比起get请求安全的多
  • get请求是可以缓存的,post请求不可以缓存(get一般是信息获取之类的,post是信息修改添加之类的,所以get不需要每次获取都去找数据库)

11.重定向和转发区别

  • 重定向浏览器URL地址栏改变,转发浏览器URL地址栏不变
  • 重定向是两次请求,转发是一次请求
  • 重定向后传输的信息会丢失(request),转发传输的信息不会丢失
  • 重定向速度不如转发

转发一般用于用户登陆,根据角色转发到相应的模块

重定向一般用于用户注销登陆时返回主页面和跳转到其它的网站等

  • 为什么说重定向是两次请求,转发是一次请求?

转发过程:

用户首先发送一个请求到服务端,服务端执行servlet后,调用getRequestDispacther方法,把请求转发给指定的xxx,整个流程都在服务端完成的,所以说转发是一次请求

重定向过程:

用户首先发送一个请求到服务端,服务端执行servlet后,调用sendRedirect方法,这个方法是response,所以是向客户端返回这个响应,响应告诉客户端需要再发送一个请求,紧接着客户端收到这个请求立即发出一个新的请求,去请求新的地址,这里两个请求互不干扰,相互独立,所以request会失效,所以说重定向是两次请求

12.servlet和jsp区别

  • jsp经过编译后就成为了Servlet
  • jsp是java和html组成成一个扩展名为jsp的文件,所以jsp侧重视图
  • servlet完全从表示层的html里分离开的,servlet侧重控制逻辑(Servlet类似于Controller,用来做控制)

13.传统api和restful api区别

f8a35f967f6b0ff2a3aa450558347d55.png

传统api是用URL来描述行为的(看URL就知道要干啥),不管成功失败都会返回200和一段json,只是可能表示是错误的json

restfulapi是用HTTP方法描述行为,用URL描述资源,使用json交互数据,使用HTTP状态码来表示不同的结果

14.jsp九大内置对象和四大作用域

九大内置对象:request、response、pageContext、session、application、out、config、page、exception

四大作用域:page(当前页面有效)、request(当前请求有效)、session(当前会话有效)、application(当前应用有效)

三.常用算法

1.排序算法

A.选择排序

B.冒泡排序

C.快速排序

2.手动实现一个ArrayList

最后

欢迎大家有兴趣的可以关注我的公众号【java小瓜哥的分享平台】,文章都会在里面更新,还有各种java的资料都是免费分享的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值