Java 中的场景题

2024年9月10日 | 11 分钟阅读

场景 1:缓存

您需要从数据库加载股票交易所证券代码及其价格,并将它们缓存起来以提高性能。证券代码需要每 30 分钟刷新一次。这些缓存数据需要由单个写入线程填充和刷新,并由多个读取线程读取。您将如何确保您的读/写解决方案具有可扩展性和线程安全性?

解决方案

java.util.concurrent.locks 包提供了实现读/写锁的类,其中读锁可以由多个线程并行执行,写锁只能由单个线程持有。ReadWriteLock 接口维护一对相关的锁,一个用于只读,一个用于写入。readLock() 可以被多个读线程同时持有,而 writeLock() 是排他的。通常,与互斥锁(即通过 synchronized 关键字)相比,当

  1. 存在更多读取操作,并且每次读取的持续时间比写入操作及其持续时间更长时,这种实现可以提高性能和可扩展性。
  2. 性能还取决于运行代码的机器,特别是如果它具有多核处理器,因为它允许更好的并行性。

Caching.java

输出

Writing .....
Reading .....12.35
Reading .....12.35

场景 2:异步处理

如果您需要通过从数据库提取数百万条历史记录来生成在线报告或文件馈送,您会提出什么问题,以及如何着手设计它?

解决方案

设计系统就是要提出正确的问题以收集需求。

在线与离线?我们是否应限制在线报告仅包含过去 12 个月的数据,以减小报告大小并提高性能,并通过离线处理提供超过 12 个月的数据的报告/馈送?例如,过去 12 个月的银行对账单在线提供,而 12 个月以上的交易则通过离线异步处理,而不会阻止客户浏览网站的其余部分。报告可以异步生成,一旦准备好,就可以通过 URL 在稍后通过电子邮件发送或下载。

使用哪个报告生成框架,如 Jasper Reports、Open CSV、XSL-FO 和 Apache FOP 等,具体取决于所需的输出格式?

如何处理异常情况?发送错误电子邮件,使用 Tivoli 或 Nagios 等监控系统在发生故障时提起生产支持工单等?

安全要求。我们是否通过电子邮件发送包含 PII(即个人身份信息)的数据的馈送/报告?我们需要适当的访问控制来限制谁可以生成哪些在线报告吗?我们应该为电子邮件附件设置密码保护吗?是否有任何合规性或监管要求,如 PCI(即支付卡行业)、GDPR(即通用数据保护条例)、ACCC(即澳大利亚竞争与消费者委员会)等,具体取决于应用程序服务的司法管辖区?

我们是否应该在非高峰时段安排离线报告运行?例如,将所有报告请求输入“请求”表,然后安排一个进程在午夜运行,以引用“请求”表中所有待处理的请求来生成并将相关报告存储在发件箱中供客户下载。可以向客户发送一封电子邮件,其中包含报告的 URL 以供下载。

历史报告的存档和清除策略。出于审计和合规目的,报告保留期是多久?文件有多大?

具有生成耗时报告或业务流程(例如,重新平衡账户、聚合分层信息等)要求的在线应用程序可以从使这些长时间运行的操作异步化中受益。一旦报告或长时间运行的业务流程完成,就可以通过电子邮件或通过称为“服务器推送(JEE 异步 Servlet)”或“客户端拉取(刷新元标记)”的技术异步刷新网页来将结果通知用户。一个典型的例子是

  1. 用户在线请求聚合报告或诸如重新平衡其投资组合之类的业务流程。
  2. 用户请求将被保存到一个数据库表中,供单独的进程定期提取并异步处理。
  3. 然后,用户可以继续执行网站的其他功能,而不会被阻塞。
  4. 在同一台机器或不同机器上运行的单独进程可以定期扫描表以获取任何条目,并生成必要的报告或执行相关的业务流程。这可以是一个在非高峰时段运行一次的计划作业,或每 10 分钟运行一次。这取决于业务需求。
  5. 一旦报告或进程完成,通过电子邮件通知用户,或使报告在线可用以下载。

场景 3:正则表达式

我们需要在 350 多个 HTML 文件中查找文本“Client”并将其更改为“Customer”。

解决方案

Regex.java

输出

All HTML files have been updated.

场景 4:并发管理

引用计数,其中共享资源被增加或减少。增量/减量操作必须是线程安全的。例如,一个计数器,它跟踪已登录用户的数量,当用户登录时增加计数,当用户注销时减少计数。有时您希望允许有限数量的并发访问,例如一次 3 个用户。

解决方案

互斥锁 (Mutex): 是对象的唯一钥匙(例如,一个厕所)。一个人可以一次拿到钥匙并占用厕所。完成后,该人将钥匙交给队列中的下一个人(或释放)。在 Java 中,每个对象都有一个互斥锁,一次只有一个线程可以获得该互斥锁。

信号量 (Semaphore): 是数量相同的空闲厕所钥匙。例如,有 3 个具有相同锁和钥匙的厕所。信号量计数最初设置为 3,然后随着人们获取厕所钥匙而递减。如果所有厕所都已满,即没有空闲钥匙了,则信号量计数为 0。现在,当一个人离开厕所时,信号量会增加到 1(一把空闲钥匙),并交给队列中的下一个人。

ConcurrencyManagement.java

输出

Semaphore is acquired
Semaphore is acquired
Semaphore is acquired
Semaphore is acquired
Semaphore is acquired
Semaphore is acquired
Semaphore is acquired
Semaphore is acquired
Semaphore is acquired
Could not acquire semaphore

场景 5:外部化业务规则

我们被要求设计一个应用程序,该应用程序使用 100 多条规则来验证数据,以符合政府合规性要求和税法。这些合规性要求可能会发生变化,并且应用程序需要能够快速轻松地适应不断变化的要求。

解决方案

利用规则引擎(如 Drools)的力量。Drools 是一个流行的开源业务规则和工作流引擎。它有助于将规则外部化到数据库表或 Excel 电子表格中,而不是嵌入到 Java 代码中。规则以“当给定($ condition)时执行($ consequence)”的形式执行。业务部门将是这些规则的保管者,这些规则可以很容易地在 Excel 电子表格中查看或通过查询数据库表来查看。可以构建一个 GUI 来维护这些存在于数据库中的规则。

场景 6:审计

我们需要维护对“客户”表的插入、修改和删除的历史记录。您将如何完成这项工作?

解决方案

  1. 创建一个 ETL(即提取、转换和加载)批处理作业,该作业定期将所有更改提取到批处理文件中,并将这些文件发送到数据仓库系统,该系统将这些批处理文件加载到 SCD Type 2 历史表中。SCD Type 2 意味着维护每次更改。这在 13 个数据仓库面试问答 - Fact vs Dimension, CDC, SCD 等中有详细讨论。
  2. 通过发布/订阅模式进行异步处理。将每个更改作为事件发布到消息导向中间件,如 Apache Kafka、Rabbit MQ、Websphere MQ 等,独立的订阅者应用程序会将每个事件保存到 SQL 或 NoSQL 历史表中。
  3. 创建数据库表触发器,将已过期的记录插入到单独的历史表中。数据库触发器是过程代码,它在特定表或视图上发生插入、更新等事件时自动执行。使用或编写触发器时必须小心,因为编写不正确或使用不当的触发器可能会严重影响数据库性能。

场景 6:学生成绩系统

有一个包含学生(姓名、成绩)的列表。我们需要找出成绩最高的女学生的姓名。

GradeSystem.java

输出

(First Method) Student with the highest grade:
Name: Daniel
Grade: 99.5
(Second Method) Student with the highest grade:
Name: Daniel
Grade: 99.5

场景 7:数据转换

给定一个字符串列表,我们必须使用 Java 8 流将其转换为大写。

UpperCaseConverter.java

输出

 [JAVA, PYTHON, REACT, JAVASCRIPT]

输出 2

JAVA
PYTHON
REACT
JAVASCRIPT

场景 8:数据过滤和排序

对于给定的元素列表,执行过滤和排序操作。编写一个 Java 8 程序来执行从列表中过滤掉奇数并将剩余的按升序排序等操作。

FilterOddNumberAndSort.java

输出

Unsorted Unfiltered List = [1, 34, 22, 13, 55, 4, 3, 87, 11, 22, 12]
Sorted Filtered List = [4, 12, 22, 22, 34]

场景 9:事务管理

对于给定的事务数据(付款人、收款人、金额),计算每个收款人收到的总金额。这里你必须使用 Java 8 的分组和求和概念。

TransactionAnalyzer.java

输出

{Mona=270.0, Charlie=150.0, Reha=210.0}
{Mona=270.0, Charlie=150.0, Reha=210.0}

场景 10:销售管理

在零售市场,不时会发生多笔交易。我们必须对收入进行数据分析。

对于给定的销售交易列表(transactionID、productID、quantity、price),我们必须找到最近 3 个月销售额排名前 N 的产品(按收入计算),使用 Java 8。

这里,N 是我们要购买的产品数量。

TopNProductsByRevenue.java

输出

Top 2 products by revenue in the last 3 months:
ProductID: 1, Revenue: 826.6999999999999
ProductID: 3, Revenue: 504.0

场景 12:员工管理系统

给定员工详细信息,我们必须根据员工姓名使用 Java 8 对员工详细信息进行排序。

EmployeeSorting.java

输出

Mohan
Rohan
Sohan