算法题目记录
数据空间研究院-后端试题
- 题目一:线程安全的链表
- 描述:
- 实现
- 题目二:自定义注解与反射
- 描述:
- 实现
- 题目三:简化的消息队列
- 描述
- 实现
题目一:线程安全的链表
描述:
实现一个线程安全的链表类 ThreadSafeLinkedList,支持以下操作:
- add(T element) - 在链表末尾添加元素。
- remove(T element) - 移除链表中的指定元素。
- contains(T element) - 检查链表中是否包含指定元素。
要求:
• 使用 Java 内置的同步机制实现线程安全。
• 不能使用 Java 内置的同步容器类(如 Collections.synchronizedList 或 CopyOnWriteArrayList)。
实现
package threadsafelist;import java.util.Objects;/*** 实现一个线程安全的链表类 threadsafelist.ThreadSafeLinkedList,支持以下操作:* 1. add(T element) - 在链表末尾添加元素。* 2. remove(T element) - 移除链表中的指定元素。* 3. contains(T element) - 检查链表中是否包含指定元素。* @param <T>*/
public class ThreadSafeLinkedList<T> {private static class Node<T> {T value;Node<T> next;Node(T value) {this.value = value;}}private final Node<T> head;private final Node<T> tail;public ThreadSafeLinkedList() {head = new Node<>(null);tail = new Node<>(null);head.next = tail;}public synchronized void add(T element) {Node<T> newNode = new Node<>(element);Node<T> current = head;while (current.next != tail) {current = current.next;}current.next = newNode;newNode.next = tail;}public synchronized boolean remove(T element) {Node<T> prev = head;Node<T> current = head.next;while (current != tail) {if (Objects.equals(element, current.value)) {prev.next = current.next;return true;}prev = current;current = current.next;}return false;}public synchronized boolean contains(T element) {Node<T> current = head.next;while (current != tail) {if (Objects.equals(element, current.value)) {return true;}current = current.next;}return false;}
}
测试代码
import threadsafelist.ThreadSafeLinkedList;public class Main {public static void main(String[] args) {ThreadSafeLinkedList<String> list = new ThreadSafeLinkedList<>();// 线程1添加元素new Thread(() -> {list.add("A");list.add("B");}).start();// 线程2检查元素new Thread(() -> {System.out.println(list.contains("A")); // 可能输出true或false}).start();}}
执行结果
“true”
题目二:自定义注解与反射
描述:
编写一个自定义注解 @LogExecutionTime,并实现一个注解处理器,当标记有该注解的方法被调用时,记录方法的执行时间并输出。
要求:
- 创建 @LogExecutionTime 注解。
- 编写一个代理类或使用 AOP(如 Spring AOP)来拦截方法调用,记录并输出方法执行时间。
- 提供一个示例类和方法,展示注解的实际应用效果。
- 需要考虑跨线程透传问题
实现
功能代码如下:
package anotation;import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface LogExecutionTime {
}
package anotation;import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;public class PerformanceHandler implements InvocationHandler {private final Object target;private static final ConcurrentMap<String, Long> methodStats = new ConcurrentHashMap<>();public PerformanceHandler(Object target) {this.target = target;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {//获取当前时间long start = System.currentTimeMillis();try {return method.invoke(target, args);} finally {long end = System.currentTimeMillis();//计算执行时间long executionTime = end - start;// 获取方法签名String methodSignature = method.getDeclaringClass().getName() + "." + method.getName();// 记录当前方法执行时间methodStats.put(methodSignature, executionTime);// 输出执行时间(支持跨线程)System.out.printf("[%s] Method %s executed in %d ms%n", // ms 而不是 nsThread.currentThread().getName(),methodSignature,executionTime);}}public static Map<String, Long> getMethodStats() {return new HashMap<>(methodStats);}
}
测试代码如下:
package anotation;import java.lang.reflect.Proxy;public class ProxyFactory {public static <T> T createProxy(Class<T> interfaceClass, T target) {Object proxy = Proxy.newProxyInstance(interfaceClass.getClassLoader(),new Class<?>[]{interfaceClass},new PerformanceHandler(target));// 运行时类型检查if (interfaceClass.isInstance(proxy)) {return interfaceClass.cast(proxy);}throw new ClassCastException("Generated proxy does not implement interface: " + interfaceClass.getName());}
}
package anotation;public interface ExampleService {void processData();String fetchData(String key);
}
package anotation;public class ExampleServiceImpl implements ExampleService{@Override@LogExecutionTimepublic void processData() {try {Thread.sleep(500); // 模拟处理耗时} catch (InterruptedException e) {Thread.currentThread().interrupt();}}@Override@LogExecutionTimepublic String fetchData(String key) {try {Thread.sleep(200); // 模拟网络请求} catch (InterruptedException e) {Thread.currentThread().interrupt();}return "Data for " + key;}
}
package anotation;public class Main {public static void main(String[] args) throws InterruptedException {ExampleService service = ProxyFactory.createProxy(ExampleService.class, new ExampleServiceImpl());// 主线程调用service.processData();// 多线程调用Thread thread1 = new Thread(() -> service.fetchData("key1"));Thread thread2 = new Thread(() -> service.fetchData("key2"));thread1.start();thread2.start();thread1.join();thread2.join();// 查看统计数据System.out.println("\nMethod execution statistics:");PerformanceHandler.getMethodStats().forEach((k, v) ->System.out.printf("Method %s last time: %d ms%n", k, v));}
}
执行结果:
[main] Method anotation.ExampleService.processData executed in 504 ms
[Thread-2] Method anotation.ExampleService.fetchData executed in 213 ms
[Thread-1] Method anotation.ExampleService.fetchData executed in 213 ms
Method execution statistics:
Method anotation.ExampleService.processData last time: 504 ms
Method anotation.ExampleService.fetchData last time: 213 ms
题目三:简化的消息队列
描述
实现一个简化的消息队列类 SimpleMessageQueue,支持以下操作:
- send(T message) - 发送消息。
- receive() - 接收消息,若队列为空,阻塞直到有消息可接收。
要求:
• 使用 java.util.concurrent 包中的工具类来实现。
• 需要保证 send 和 receive 操作的线程安全。
• 提供单元测试,验证消息队列的正确性。
实现
功能代码
package simplemessagequeue;import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;public class SimpleMessageQueue<T> {private final BlockingQueue<T> queue = new LinkedBlockingQueue<>();// 发送消息public void send(T message) {try {queue.put(message);} catch (InterruptedException e) {Thread.currentThread().interrupt();throw new RuntimeException("Send interrupted", e);}}// 接收消息,若队列为空则阻塞public T receive() {try {return queue.take();} catch (InterruptedException e) {Thread.currentThread().interrupt();throw new RuntimeException("Receive interrupted", e);}}
}
测试代码
package simplemessagequeue;public class SimpleMessageQueueTest {public static void main(String[] args) throws InterruptedException {SimpleMessageQueue<String> queue = new SimpleMessageQueue<>();// 测试单线程收发queue.send("hello");assert "hello".equals(queue.receive());// 测试多线程收发Thread sender = new Thread(() -> {for (int i = 0; i < 5; i++) {queue.send("msg" + i);}});Thread receiver = new Thread(() -> {for (int i = 0; i < 5; i++) {String msg = queue.receive();System.out.println("Received: " + msg);}});sender.start();receiver.start();sender.join();receiver.join();System.out.println("All tests passed.");}
}
运行结果
Received: hello
Received: msg0
Received: msg1
Received: msg2
Received: msg3
All tests passed.