Seeker的奇妙求职历险(招行提前批)

招行提前批

  • 前言
  • 磁盘调度策略
  • 吞吐量的计算
  • 代理模式
    • 静态代理
    • 动态代理
    • 使用CGlib动态代理
    • 在SpringBoot中使用代理
  • Scanner

前言

6月22日做了招银科技提前批的笔试题目,深受打击,有好多不会做的题目。

磁盘调度策略

磁盘调度策略常用的一般有4种:

  • 先来先服务:没什么好说的,读到哪里算哪里。
  • 最短寻道时间优先算法(SSTF):先读取离当前位置距离最近的一个请求。
  • 扫描算法(SCAN):类似于电梯算法。
  • 循环扫描算法(CSCAN):是电梯算法的一半,当扫描到最后一个磁道的时候,不从后往前扫描,而是重新回到最小的一个欲访问磁道,继续扫描。就是一个只往上的电梯(回来时候不停,直接到1层)。这样可以防止某个后来的磁道比较小的请求不等待太长时间。

举个例子:假定某磁盘共有200个柱面,编号为0-199,如果在为访问143号柱面的请求者服务后,当前正在为访问125号柱面的请求服务,同时有若干请求者在等待服务,它们每次要访问的柱面号为 86,147,91,177,94,150,102,175,130。
那么SSTF的访问次序是(125)130,147,150,175,177,102,94,91,86。
SCAN的访问次序是(125)102,94,91,86,130,147,150,175,177。
而CSCAN的次序是(125)130,147,150,175,177,86,91,94,102。

吞吐量的计算

假定链路带宽是100Mbps,TCP滑动窗口最大是65535字节,源地址和目标地址的传输延时是20ms,求最大吞吐量。
公式制作网址

65535 × 8 ÷ ( 20 × 1 0 − 3 ) ÷ ( 1000 × 1024 ) ≈ 26 M b p s 65535\times8\div(20\times10^{-3})\div(1000\times1024)\approx26Mbps 65535×8÷(20×103)÷(1000×1024)26Mbps
意在20ms之间内发送滑动窗口内的所有比特(所以要乘以8)

代理模式

这次的编程第二题是动态代理的题目,之前没有关注过,所以这一次就没有做出来。
内容来源:Java 中的代理(proxy)

静态代理

静态代理需要实现一个接口、一个真实对象和一个代理对象(两者都要实现这个接口)。静态代理实现比较简单,但是在实际工作中用的很少。我之前在网吧项目中写过代理类,主要是为了在读取消息的时候先进行一些操作,不过那时候我还不知道我写的居然是大名鼎鼎的代理类

//接口
interface Shopping{
	void buy();
}
//实际类
class Client implements Shopping{
	public void buy(){
		System.out.prinln("我想买这件商品");
	}
}
//代理类
class StaticProxy implements Shopping{
	private Shopping shopping;
	public StaticProxy(Shopping shopping){
		this.shopping = shopping;
	}
	public void buy(){
		System.out.println("降价");
		shopping.buy();
	}
}

public class StaticProxyTest{
	public static void main(String[] args){
		Client client = new Client();
		StaticProxy service = new StaticProxy(client);
		service.buy();
	}
}

动态代理

动态代理是在运行时生成代理类,主要借助于java.lang.reflect包中的Proxy类与InvoationHandler接口,所有对动态代理对象的方法调用都会转发到InvovationHandler中的invoke()方法中实现。一般我们称实现了InvovationHandler接口的类为调用处理器(这个接口要注意一下,前几天看腾讯面经的时候有人被问到了这个)。
先介绍一下方法newProxyInstance,这个方法的参数也很好记,让我们回想一下Spring中介绍JDK代理的时候:Spring会为实现接口的类创建一个JDK代理,所以动态代理的接口前两个参数就是类加载器和类所需要的接口,最后一个参数就是增强了原来类的代理类。

public static Object newProxyInstance(ClassLoader loader,
										Class<?> interfaces,
										InvocationHandler h)
public class DynamicProxy implements InvocationHandler{
	private Object target = null;
	DynamicProxy(){}
	DynamicProxy(Object target){
		this.target = target;
	}
	public Object getProxyInstance(Object target){
		this.target = target;
		return Proxy.newProxyInstance(target.getClass().getClassLoader(),
						target.getClass().getInterfaces(),
						this);
	}
	@Override
	public Object invoke(Object proxy,Method method,Object[] args)
												throws Throwable{
		System.out.println("代理前");
		//招银那道题坑爹的地方还在于居然要获取方法的自定注释。
		if(method.hasAnnotations())
			method.getAnnotations(Method.getName());
		method.invoke(target,args);
		System.out.println("代理后");
		return proxy;
	}
}
//要是用的时候
public static main(String[] args){
	Client client = new Client();
	DynamicProxy dyProxy = new DynamicProxy();
	Shopping shop = (Shopping)dyProxy.getProxyInstance(client);
	shop.buy();
}

使用CGlib动态代理

上面的代码是基于JDK的代理,如果类没有实现接口,Spring会为其生成CGlib代理类(网吧服务器的组件就是没有接口直接实现的类,所以日志里经常能见到CGlib$字样)。
CGlib的接口就不是InvovationHandler了,采用的是MethodInterceptor接口,原理是生成被代理类的子类,所以不需要实现接口,但是如果被代理类是final修饰的则不能代理。

public class CglibProxy implements MethodInterceptor{
	public <T> T getProxy(Class<T> clazz){
		return (T)Enhancer.create(clazz,this);
	}
	@Override
	public Object intercept(Object o,Method method,
									Object[] objects,
					MethodProxy methodProxy) throws Throwable{
		System.out.println("代理前");
		Object result = methodProxy.invokeSuper(o,objects);
		System.out.println("代理后");
		return result;
	}
}

在SpringBoot中使用代理

其实都0202年了,谁还自己手写代理,直接用注解不香吗?

@Component
@Aspect
public class AOP{
	//execution后面加的是包地址,可以通过正则匹配
	@Before("execution(* aa.*.*(..))")
	public void begin(){
		System.out.println("代理前");
	}
}

Scanner

在力扣和牛客上题目做的多了,都忘记在有些OJ上输入是要自己读取的了,然后今天在做题目的时候就发现不知道怎么读取一个输出。
其实在Java中读取输入一般使用的就是Scanner函数。

Scanner scan = new Scanner(System.in);
//数据太多导致超时
Scanner scanner = new Scanner(new BufferedInputStream(System.in));
if(scan.hasNext()){
	//字符读取
	String i = scan.next();
}
if(scan.hasNextInt()){
	//行读取
	String i = scan.nextLine();
}
if(scan.hasNextInt()){
	//整型读取
	int i = scan.nextInt();
}
if(scan.hasNextFloat()){
	//浮点数读取
	Float i = scan.nextFloat();
}
if(scan.hasNextDouble()){
	//浮点数读取
	Double i = scan.nextDouble();
}

你可能感兴趣的:(Seeker的奇妙求职历险)