面试题答案
一键面试原理
Collections.synchronizedQueue
实现线程安全队列的原理是通过对队列的所有操作(如添加、移除、检查等)进行同步包装。它内部使用了一个对象锁,在对队列进行任何修改或读取操作时,都需要先获取该锁,从而保证同一时间只有一个线程可以访问队列,避免了多线程并发访问导致的数据不一致问题。
使用示例
import java.util.Queue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.Collections;
public class SynchronizedQueueExample {
public static void main(String[] args) {
// 创建一个普通的Queue
Queue<Integer> queue = new LinkedBlockingQueue<>();
// 使用Collections.synchronizedQueue将其包装成线程安全的Queue
Queue<Integer> synchronizedQueue = Collections.synchronizedQueue(queue);
// 模拟多线程操作
Thread producer = new Thread(() -> {
for (int i = 0; i < 10; i++) {
synchronizedQueue.add(i);
System.out.println("Produced: " + i);
}
});
Thread consumer = new Thread(() -> {
while (true) {
Integer item = synchronizedQueue.poll();
if (item != null) {
System.out.println("Consumed: " + item);
} else {
break;
}
}
});
producer.start();
consumer.start();
try {
producer.join();
consumer.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
性能问题
- 竞争开销:由于所有操作都需要获取锁,当多个线程频繁访问队列时,锁的竞争会变得非常激烈,导致大量线程等待锁的释放,从而增加线程上下文切换的开销,降低系统整体性能。
- 串行化操作:因为同一时间只有一个线程能访问队列,使得原本可以并行执行的操作变成了串行执行,特别是在高并发环境下,这会成为性能瓶颈。例如,一个线程在执行队列的添加操作时,其他线程无论是想添加还是移除元素都必须等待,即使这些操作在逻辑上并不冲突。