内容概括
常见题目
1.实际工作中使用的设计模式
2.接口和抽象类的对比
3.引用类型 4种
4.为什么反射性能差
5.IO的设计模式有哪些
题目:发布订阅模式 · Pub Sub Pattern
描述中文
发布/订阅模式是系统设计中广泛使用的模式。 在此问题中,您需要实现发布/订阅模式以支持特定频道上的用户订阅,并从订阅的频道获取通知消息。
您需要实现3种方法:
subscribe(channel,user_id)
:将给定用户订阅到给定频道。unsubscribe(channel,user_id)
:取消订阅给定用户的给定用户。publish(channel,message)
:您需要将消息发布到频道,以便在频道上订阅的每个人都会收到此消息。 调用PushNotification.notify(user_id,message)
将消息推送给用户。
样例
subscribe("group1", 1)
publish("group1", "hello")
>> user 1 received "Hello"
subscribe("group1", 2)
publish("group1", "thank you")
>> user 1 received "thank you"
>> user 2 received "thank you"
unsubscribe("group2", 3)
>> user 3 is not in group2, do nothing
unsubscribe("group1", 1)
publish("group1", "thank you very much")
>> user 2 received "thank you very much"
publish("group2", "are you ok?")
>> # you don't need to push this message to anyone
如果在同一频道上订阅的用户超过1个,则用户接收该消息的时间顺序无关紧要。 您可以在将消息推送给用户1之前推送给用户2。
public class PubSubPattern {
private HashMap<String, HashSet<Integer>> channels;
public PubSubPattern(){
channels = new HashMap<String, HashSet<Integer>>();
}
public void subscribe(String channel, int user_id) {
if (!channels.containsKey(channel)) {
channels.put(channel, new HashSet<Integer>());
}
HashSet<Integer> user_ids = channels.get(channel);
user_ids.add(user_id);
}
public void unsubscribe(String channel, int user_id) {
if (!channels.containsKey(channel)) {
return;
}
HashSet<Integer> user_ids = channels.get(channel);
user_ids.remove(user_id);
}
public void publish(String channel, String message) {
if (!channels.containsKey(channel)) {
return;
}
for (Integer user_id : channels.get(channel)) {
PushNotification.notify(user_id, message);
}
}
}
题目:电梯系统
描述中文
题目:为一栋大楼设计电梯系统
- 不需要考虑超重的情况
- 该电梯系统目前只有1台电梯, 该楼共有
n
层 - 每台电梯有三种状态:上升,下降,空闲
- 当电梯往一个方向移动时,在电梯内无法按反向的楼层
我们提供了其他几个已经实现好的类,你只需要实现Elevator Class
内的部分函数即可。
注意:
Currently elevator status is : DOWN.
是指现在正在执行 down stop list
里的命令
Currently elevator status is : UP.
是指现在正在执行 up stop list
里的命令
每行命令之后我们都会调用elevatorStatusDescription 函数,用于测试你是否处于一个正确的状态。
样例
样例1
输入:
5
ExternalRequest(3, "Down")
ExternalRequest(1, "Up")
openGate()
closeGate()
openGate()
closeGate()
输出:
Currently elevator status is : DOWN.
Current level is at: 1.
up stop list looks like: [false, false, false, false, false].
down stop list looks like: [false, false, true, false, false].
*****************************************
Currently elevator status is : DOWN.
Current level is at: 1.
up stop list looks like: [true, false, false, false, false].
down stop list looks like: [false, false, true, false, false].
*****************************************
Currently elevator status is : DOWN.
Current level is at: 3.
up stop list looks like: [true, false, false, false, false].
down stop list looks like: [false, false, false, false, false].
*****************************************
Currently elevator status is : UP.
Current level is at: 3.
up stop list looks like: [true, false, false, false, false].
down stop list looks like: [false, false, false, false, false].
*****************************************
Currently elevator status is : UP.
Current level is at: 1.
up stop list looks like: [true, false, false, false, false].
down stop list looks like: [false, false, false, false, false].
样例2
输入:
5
ExternalRequest(3, "Down")
ExternalRequest(2, "Up")
openGate()
InternalRequest(1)
closeGate()
openGate()
closeGate()
openGate()
closeGate()
输出:
Currently elevator status is : DOWN.
Current level is at: 1.
up stop list looks like: [false, false, false, false, false].
down stop list looks like: [false, false, true, false, false].
*****************************************
Currently elevator status is : DOWN.
Current level is at: 1.
up stop list looks like: [false, true, false, false, false].
down stop list looks like: [false, false, true, false, false].
*****************************************
Currently elevator status is : DOWN.
Current level is at: 3.
up stop list looks like: [false, true, false, false, false].
down stop list looks like: [false, false, false, false, false].
*****************************************
Currently elevator status is : DOWN.
Current level is at: 3.
up stop list looks like: [false, true, false, false, false].
down stop list looks like: [true, false, false, false, false].
*****************************************
Currently elevator status is : DOWN.
Current level is at: 3.
up stop list looks like: [false, true, false, false, false].
down stop list looks like: [true, false, false, false, false].
*****************************************
Currently elevator status is : DOWN.
Current level is at: 1.
up stop list looks like: [false, true, false, false, false].
down stop list looks like: [false, false, false, false, false].
*****************************************
Currently elevator status is : UP.
Current level is at: 1.
up stop list looks like: [false, true, false, false, false].
down stop list looks like: [false, false, false, false, false].
*****************************************
Currently elevator status is : UP.
Current level is at: 2.
up stop list looks like: [false, false, false, false, false].
down stop list looks like: [false, false, false, false, false].
*****************************************
Currently elevator status is : IDLE.
Current level is at: 2.
up stop list looks like: [false, false, false, false, false].
down stop list looks like: [false, false, false, false, false].
*****************************************
enum Direction {
UP, DOWN
}
enum Status {
UP, DOWN, IDLE
}
class Request {
private int level;
public Request(int l) {
level = l;
}
public int getLevel() {
return level;
}
}
class ElevatorButton {
private int level;
private Elevator elevator;
public ElevatorButton(int level, Elevator e) {
this.level = level;
this.elevator = e;
}
public void pressButton() {
InternalRequest request = new InternalRequest(level);
elevator.handleInternalRequest(request);
}
}
class ExternalRequest extends Request {
private Direction direction;
public ExternalRequest(int l, Direction d) {
super(l);
// TODO Auto-generated constructor stub
this.direction = d;
}
public Direction getDirection() {
return direction;
}
}
class InternalRequest extends Request {
public InternalRequest(int l) {
super(l);
// TODO Auto-generated constructor stub
}
}
public class Elevator {
private List<ElevatorButton> buttons;
private List<Boolean> upStops;
private List<Boolean> downStops;
private int currLevel;
private Status status;
public Elevator(int n) {
buttons = new ArrayList<ElevatorButton>();
upStops = new ArrayList<Boolean>();
downStops = new ArrayList<Boolean>();
currLevel = 0;
status = Status.IDLE;
for (int i = 0; i < n; i++) {
upStops.add(false);
downStops.add(false);
}
}
public void insertButton(ElevatorButton eb) {
buttons.add(eb);
}
public void handleExternalRequest(ExternalRequest r) {
if (r.getDirection() == Direction.UP) {
upStops.set(r.getLevel() - 1, true);
if (noRequests(downStops)) {
status = Status.UP;
}
} else {
downStops.set(r.getLevel() - 1, true);
if (noRequests(upStops)) {
status = Status.DOWN;
}
}
}
public void handleInternalRequest(InternalRequest r) {
// check valid
if (status == Status.UP) {
if (r.getLevel() >= currLevel + 1) {
upStops.set(r.getLevel() - 1, true);
}
} else if (status == Status.DOWN) {
if (r.getLevel() <= currLevel + 1) {
downStops.set(r.getLevel() - 1, true);
}
}
}
public void openGate() throws Exception {
if (status == Status.UP) {
for (int i = 0; i < upStops.size(); i++) {
int checkLevel = (currLevel + i) % upStops.size();
if (upStops.get(checkLevel)) {
currLevel = checkLevel;
upStops.set(checkLevel, false);
break;
}
}
} else if (status == Status.DOWN) {
for (int i = 0; i < downStops.size(); i++) {
int checkLevel = (currLevel + downStops.size() - i) % downStops.size();
if (downStops.get(checkLevel)) {
currLevel = checkLevel;
downStops.set(checkLevel, false);
break;
}
}
}
}
public void closeGate() {
if (status == Status.IDLE) {
if (noRequests(downStops)) {
status = Status.UP;
return;
}
if (noRequests(upStops)) {
status = Status.DOWN;
return;
}
} else if (status == Status.UP) {
if (noRequests(upStops)) {
if (noRequests(downStops)) {
status = Status.IDLE;
} else {
status = Status.DOWN;
}
}
} else {
if (noRequests(downStops)) {
if (noRequests(upStops)) {
status = Status.IDLE;
} else {
status = Status.UP;
}
}
}
}
private boolean noRequests(List<Boolean> stops) {
for (int i = 0; i < stops.size(); i++) {
if (stops.get(i)) {
return false;
}
}
return true;
}
public String elevatorStatusDescription() {
String description = "Currently elevator status is : " + status
+ ".\nCurrent level is at: " + (currLevel + 1)
+ ".\nup stop list looks like: " + upStops
+ ".\ndown stop list looks like: " + downStops
+ ".\n*****************************************\n";
return description;
}
}
高频面试题
1.实际工作中使用的设计模式
2.接口和抽象类的对比
3.引用类型 4种
4.为什么反射性能差
5.IO的设计模式有哪些
答疑问题
集合
扩容过程中,如果新数据过来,加在哪里?2扩容是直接停下来扩容,还是写时复制
为什么链表是8(柏松分布)
引用类型
虚引用有什么意义?他的作用是什么?
虚引用的存在就是为了跟踪某个对象是否被回收掉了,虚引用存在的价值不大,最主要就是做对象跟踪用的,引用队列的作用可以用作其他引用对象,队列中引用被回收以后加入到引用队列中
数据类型
接口和抽象类的区别?
什么时候用接口,什么时候用抽象类?
接口和抽象类的区别?
接口:单纯的对行为的一种抽象
抽象类:对一些类的公共部分的抽象
Java反射
反射是如何体现面向对象的思想的?/怎么理解反射是面向对象的一种应用的?
答:面向对象就是对一种事物的抽象,而反射就是吧Java本身进行抽象,比如Class,Method,Value,因此可以动态的实现类以及执行一些方法和调用属性,所以说反射是面向对象的一种体现。
反射为何能差?
1. Class.forName,Class.getMethod 涉及native调用;符号引用转为直接引用;getMethod涉及遍历查找
2. Method.invoke 变长参数方法传的 Object 数组 ->基本类型的自动装箱、拆箱 -> 堆分配空间;涉及native调用;
3. 安全检查
4. jvm没办法jit优化
如何优化反射的性能?
1. 缓存访问的元素
2. 接口优先于反射
3. 字节码增强(第一次使用会很慢,后面就相当于转成直接调用了)
4. 魔法类:sun.misc.Unsafe
设计模式
设计模式中懒汉模式双重检查枷锁的类需要添加volatile关键字进行修饰
引用类型
这么说,大家估计乱套了,群里的小伙伴估计都蒙了,我总结下说法吧,我不敢保证对不对,请大家指出问题,根据官方api: https://docs.oracle.com/en/java/javase/15/docs/api/java.base/java/lang/ref/PhantomReference.html, 虚引用主要用来做一些对象的善后操作,Java中我们可以通过分配一块堆外内存,比如NIO中的 DirectByteBuffer,为啥要复制到堆外呢,是因为,我们一般做IO操作,需要把堆内存中的东西先拉到操作系统地内存中,也就是有的小伙伴提到的,用户态,内核态,如果我们直接在堆外内存分配,那么我们就可能减少一次IO复制,大家理解到这就可以,至于虚引用与这个东西的关系,其实并没有太大关系,不能说我初始化一个对象,传入一个int类型,你就要说int与对象初始化是必须绑定的,虚引用官方文档说的很清楚了,就是一般处理对象的善后操作,我们创建一个堆外内存,既然堆的回收器无法回收,我们必然想办法,所以,通过继承虚引用,是不是就将堆外的对象与堆内的垃圾回收对象保持了某种关系,然后当我们堆内发生GC的时候,我们是不是就可以通知unsafe类去回收堆外对象,当然说是这么说,实现可能不是这样,我只是看了nio文档中的那个继承虚引用的对象代码,感觉是这么回事
实际上还有个类似功能的叫 FinalReference,和finalize有关,有点偏的知识点。
大家了解就行,暂时不用纠结,时间宝贵,先学主要的。