java面试Day14

1.如何使用 Redis 实现一个排行榜?

Redis实现排行榜是Redis中一个很常见的场景,主要使用的是ZSet进行实现,下面是为什么选用ZSet:

  • 有序性:排行榜肯定需要实现一个排序的功能,在Redis中有序的数据结构有List和ZSet;

  • 支持分数操作:ZSet可以对集合中的元素进行增删改查操作,十分贴合排行榜中用户分数动态变化的场景,而List并不能针对分数进行操作,只有其中的value进行操作;

  • 支持范围查询:ZSet可以按照分数进行范围查询,如排行榜中的Top10需求就可通过该特性进行实现;

  • 支持去重:由于ZSet属于Set的特殊数据结构,因此同样拥有Set不可重复的特性,对于排行榜中不可出现重复项的需求也十分贴合,而List只能手动去重。

因此选择ZSet实现排行榜相对于List实现会更合适和高效。

以学生成绩排行为例,下面是使用Redis命令实现

# 添加示例数据
ZADD scores 90 "张三"
ZADD scores 85 "李四"
ZADD scores 95 "王五"
ZADD scores 92 "赵六"
# 查询排名前3的学生信息
ZRANGE scores 0 2 WITHSCORES
# 查询排名前3的打印
1) "王五"
2) "95"
3) "赵六"
4) "92"
5) "张三"
6) "90"
# 删除学生“李四”的成绩信息
ZREM scores "李四"

下面是SpringBoot整合Redis进行实现

// 添加学生成绩
public void addScore(String name, int score) {
    redisTemplate.opsForZSet().add("scores", name, score);
}
​
// 查询排名前N的学生成绩
public List<Map.Entry<String, Double>> getTopScores(int n) {
    return redisTemplate.opsForZSet().reverseRangeWithScores("scores", 0, n - 1)
            .stream()
            .map(tuple -> new AbstractMap.SimpleEntry<>(tuple.getValue(), tuple.getScore()))
            .collect(Collectors.toList());
}
​
// 删除某个学生的成绩
public void removeScore(String name) {
    redisTemplate.opsForZSet().remove("scores", name);
}

2.什么是网关,网关有哪些作用?

网关(Gateway)是在计算机网络中用于连接两个独立的网络的设备,它能够在两个不同协议的网络之间传递数据。在互联网中,网关是一个可以连接不同协议的网络的设备,比如说可以连接局域网和互联网,它可以把局域网的内部网络地址转换成互联网上的合法地址,从而使得局域网内的主机可以与外界通信。

在计算机系统中,网关可以用于实现负载均衡、安全过滤、协议转换等功能。具体来说,网关可以分为以下几种:

  1. 应用网关:用于应用层协议的处理,如 HTTP、SMTP 等。(Nginx、HA Proxy)

  2. 数据库网关:用于数据库访问的控制和管理。

  3. 通信网关:用于不同通信协议之间的数据交换,如 TCP/IP、UDP/IP 等。

  4. API 网关:用于管理和转发 API 请求,实现 API 的授权、限流、监控等功能。( Spring Cloud Gateway )

网关的作用如下:

  1. 实现协议的转换:不同网络之间通常使用不同的协议,通过网关可以实现协议的转换,使得不同网络之间能够相互通信。

  2. 提供数据转发功能:网关可以对传输的数据进行过滤、路由、转发等处理,确保数据的可靠传输。

  3. 实现安全策略:网关可以对传输的数据进行加密、认证、授权等操作,保证数据的安全性和可靠性。

  4. 提供缓存功能:网关可以将一部分数据缓存起来,提高数据的访问速度和响应性能。

  5. 支持负载均衡:网关可以将请求分配到不同的服务器上,实现负载均衡,提高系统的可用性和性能。

  6. 实现访问控制:网关可以对访问进行控制,防止未授权的访问和攻击,提高系统的安全性。

总的来说,网关可以为不同网络提供连接和通信的功能,同时也可以提供安全、性能、可靠性等方面的增强功能,是现代计算机系统中不可或缺的一部分。

针对Spring Cloud Gateway:

官网:Spring Cloud Gateway

网关出现的原因是微服务架构的出现,不同的微服务一般会有不同的网络地址,而外部客户端可能需要调用多个服务的接口才能完成一个业务需求。如果让客户端直接与各个微服务通信,会有以下的问题:

  • 客户端会多次请求不同的微服务,增加了客户端的复杂性;

  • 存在跨域请求,在一定场景下处理相对复杂;

  • 认证复杂,每个服务都需要独立认证;

  • 难以重构,随着项目的迭代,可能需要重新划分微服务。例如,可能将多个服务合并成一个或者将一个服务拆分成多个。而划分出多个微服务就代表可能出现多个新的访问地址,如果客户端直接与微服务通信,那么重构将会很难实施;

  • 某些微服务可能使用了防火墙/浏览器不友好的协议,直接访问会有一定的困难;

那么使用网关的好处就如下:

  • 路由

  • 负载均衡

  • 统一鉴权

  • 跨域

  • 统一业务处理

  • 访问控制

  • 发布控制

  • 流量染色

  • 接口保护

  • 同一日志

  • 统一文档

常见的网关产品有Tyk,Kong,Zuul以及Spring Cloud Gateway

3.线程的生命周期是什么,线程有几种状态,什么是上下文切换?

来自:Starry、黑马程序员

1、六种状态 Java中有六种状态:新建状态(New)、就绪状态(Runnable)、阻塞状态(Blocked)、等待状态(Waiting)、超时等待(Timed_Waiting)、终止状态(Terminated)

  • NEW:初始状态,线程被创建出来但没有被调用 start() 。

  • RUNNABLE:运行状态,线程被调⽤了 start() 等待运行的状态。

  • BLOCKED:阻塞状态,需要等待锁释放。

  • WAITING:等待状态,表示该线程需要等待其他线程做出⼀些特定动作(通知或中断)。

  • TIME_WAITING:超时等待状态,可以在指定的时间自行返回而不是像 WAITING 那样⼀直等待。

  • TERMINATED:终⽌状态,表示该线程已经运行完毕。

2、五种状态

操作系统层面的划分,线程有五种状态:新建、就绪、运行、阻塞和死亡状态。

  1. 新建状态(New) : 新创建了一个线程对象

  2. 就绪状态(runnable) : 线程对象创建后,其他线程调用了该对象的 start 方法。该状态的线程位于可运行线程池中,变得可运行,等待获取CPU的使用权

  3. 运行状态(Running) : 就绪状态的线程获取了 CPU,执行程序代码

  4. 阻塞状态(Blocked):阻塞状态是线程因为某种原因放弃CPU使用权,暂时停止运行。直到线程进入就绪状态,才有机会转到运行状态

  5. 死亡状态(Dead) :线程执行完了或者因异常退出了 run 方法,该线程结束生命周期。

阻塞情况又分为三种:

  1. 等待阻塞:运行的线程执行 wait 方法,该线程会释放占用的所有资源,JVM会把该线程放入 "等待池"中,进入这个状态后,是不能自动唤醒的,必须依靠其他线程调用 notify 或者 notifyAll 方法才能被唤醒,wait 是object 类的方法。

  2. 同步阻塞:运行的线程在获取对象的同步锁时,若该同步锁被别的线程占用,则 JVM 会把该线程放入 "锁池"中。

  3. 其他阻塞:运行的线程执行 sleep 或者 join 方法,或者发出了 I/O请求时,JVM 会把该线程设置为阻塞状态。当 sleep 状态超时、join 等待线程终止或者超时、或者 I/O处理完毕时,线程重新转入就绪状态。 sleep 是 Thread 类的方法。

3、上下文切换

线程的状态变化通常是由操作系统进行管理和控制的,当线程状态发生变化时,需要进行上下文切换。

上下文切换是指将当前线程的状态保存下来,并将CPU资源切换到另一个线程上运行的过程。上下文切换需要花费一定的时间和系统资源,因此,线程的上下文切换次数要尽量减少,以提高系统的性能。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值