Java面试突击案例大全
我为你整理了一套高频面试题 + 实战案例,分为基础、进阶、框架、系统设计四个层次,每个案例都附有代码和解析。

Java基础高频面试题
HashMap底层原理(必考)
// 面试官:说一下HashMap的put流程
// 完整回答思路:
public class HashMapDemo {
public static void main(String[] args) {
HashMap<String, Integer> map = new HashMap<>();
map.put("key1", 1);
// put流程:
// 1. 计算hash:hash(key) = (h = key.hashCode()) ^ (h >>> 16)
// 2. 如果table为null,调用resize()初始化,默认容量16
// 3. 计算索引:(n - 1) & hash
// 4. 如果该位置为null,直接插入
// 5. 不为null,判断是链表还是红黑树
// - 链表长度 >= 8 且数组长度 >= 64 → 转红黑树
// - 链表长度 >= 8 但数组长度 < 64 → 先扩容
// 6. 插入后size > threshold(容量*0.75),扩容为2倍
}
}
并发编程核心(必考)
// 问题:如何实现线程安全的单例?为什么推荐枚举方式?
public class SingletonDemo {
// 方式1:双重检查锁(DCL)- 需要volatile防止指令重排序
private static volatile SingletonDemo instance;
private SingletonDemo() {}
public static SingletonDemo getInstance() {
if (instance == null) {
synchronized (SingletonDemo.class) {
if (instance == null) {
instance = new SingletonDemo(); // 不是原子操作!
}
}
}
return instance;
}
// 方式2:静态内部类 - 线程安全且懒加载
private static class Holder {
private static final SingletonDemo INSTANCE = new SingletonDemo();
}
public static SingletonDemo getInstance2() {
return Holder.INSTANCE;
}
// 方式3:枚举(最推荐) - 天然防止反射和序列化破坏
// 详见下方
}
内存模型与垃圾回收(必考)
// 面试官:Java对象在内存中如何分配?
// 回答要点:
public class JVMDemo {
// 对象创建流程:
// 1. 类加载检查 → 2. 分配内存(指针碰撞 / 空闲列表)
// 3. 内存空间初始化(零值) → 4. 设置对象头
// 5. 执行<init>方法
// GC Roots有哪些?
// ① 虚拟机栈中引用的对象(局部变量)
// ② 方法区中静态属性引用的对象(static变量)
// ③ 方法区中常量引用的对象(final常量)
// ④ 本地方法栈中JNI引用的对象
// 判断对象存活:可达性分析(从GC Roots出发,不可达即回收)
// 不是引用计数法!(循环引用问题)
}
高效实战用例
场景1:千万级用户订单系统 - 并发处理
public class OrderService {
// 问题:如何保证订单号不重复?
// 方案1:数据库自增ID(分库分表时需使用雪花算法)
@Autowired
private RedisTemplate<String, String> redisTemplate;
// 雪花算法生成唯一ID
public long generateOrderId() {
// Snowflake算法:1位符号位 + 41位时间戳 + 10位机器ID + 12位序列号
// 每秒可生成409.6万个ID
return SnowflakeIdGenerator.getInstance().nextId();
}
// 防止超卖:分布式锁+乐观锁
public boolean createOrder(Long userId, Long productId, int count) {
// 方式1:Redis分布式锁(面试重点)
String lockKey = "lock:product:" + productId;
Boolean locked = redisTemplate.opsForValue()
.setIfAbsent(lockKey, "1", 10, TimeUnit.SECONDS);
if (!locked) {
return false; // 获取锁失败
}
try {
// 检查库存(乐观锁:version字段)
// update t_product set stock = stock - #{count}
// where id = #{productId} and stock >= #{count}
// 扣减库存
// 创建订单
return true;
} finally {
// 释放锁(必须用Lua脚本保证原子性)
redisTemplate.delete(lockKey);
}
}
}
场景2:超时订单自动关闭 - 延迟队列
// 问题:如何高效处理超时未支付订单?
// 方案1:Redis过期监听(简单但不可靠)
// 方案2:消息队列延迟消息(推荐)
@Component
public class OrderTimeoutConsumer {
// RabbitMQ延迟队列实现
// 原理:消息先进入死信交换机,延迟时间后再投递到业务队列
@RabbitListener(queues = "order.timeout.queue")
public void handleTimeoutOrder(Order order) {
// 1. 检查订单状态
Order dbOrder = orderMapper.selectById(order.getId());
if (dbOrder.getStatus() == OrderStatus.UNPAID) {
// 2. 自动取消订单
orderMapper.updateStatus(order.getId(), OrderStatus.CANCELLED);
// 3. 恢复库存
stockService.restoreStock(order.getProductId(), order.getCount());
}
}
}
场景3:缓存穿透、击穿、雪崩的解决方案
@Service
public class CacheService {
// 1. 缓存穿透:查询不存在的数据
// 解决方案:布隆过滤器
public String getProductInfo(Long productId) {
// 先查布隆过滤器
if (!bloomFilter.mightContain("product:" + productId)) {
return null; // 肯定不存在,直接返回
}
// 2. 缓存空值(额外方案)
String value = redisTemplate.opsForValue().get("product:" + productId);
if (value == null) {
value = productMapper.selectById(productId);
if (value == null) {
// 缓存空值,设置较短过期时间(如5分钟)
redisTemplate.opsForValue().set("product:" + productId, "null", 300, TimeUnit.SECONDS);
return null;
}
}
return value;
}
// 2. 缓存击穿:热点key过期瞬间大量请求
// 解决方案:互斥锁
@Transactional
public String getHotProduct(Long productId) {
String key = "product:" + productId;
String value = redisTemplate.opsForValue().get(key);
if (value != null) return value;
// 加锁查询数据库(只让一个请求去查库)
String lockKey = "lock:" + key;
Boolean locked = redisTemplate.opsForValue()
.setIfAbsent(lockKey, "1", 3, TimeUnit.SECONDS);
if (locked) {
try {
value = productMapper.selectById(productId);
redisTemplate.opsForValue().set(key, value, 3600, TimeUnit.SECONDS);
return value;
} finally {
redisTemplate.delete(lockKey);
}
} else {
// 其他请求等等,然后重试
try { Thread.sleep(100); } catch (InterruptedException e) {}
return getHotProduct(productId); // 递归重试
}
}
// 3. 缓存雪崩
// 解决方案:
// - 设置不同的过期时间:baseTime + random
// - 缓存数据永不过期,后台定时刷新
public void setProductCache(Long productId, String value) {
int timeout = 3600 + new Random().nextInt(600); // 随机60-70分钟
redisTemplate.opsForValue().set("product:" + productId, value, timeout, TimeUnit.SECONDS);
}
}
分布式系统设计经典案例
案例:设计一个短链接系统
// 需求:长链接转为短链接,支持跳转
// 核心设计:
public class ShortUrlService {
// 1. 生成短码:使用发号器(Redis INCR)或雪花算法
public String createShortUrl(String longUrl) {
// 发号器生成唯一ID
long id = redisTemplate.opsForValue().increment("short:url:id");
// 将ID转为62进制(0-9a-zA-Z)
String shortCode = base62Encode(id); // 10进制→62进制
// 存储映射关系
redisTemplate.opsForValue().set("short:" + shortCode, longUrl);
return "https://t.cn/" + shortCode;
}
// 2. 跳转:redis找不到则查数据库
public String getLongUrl(String shortCode) {
String longUrl = redisTemplate.opsForValue().get("short:" + shortCode);
if (longUrl == null) {
// 查数据库,然后回填缓存
UrlMap urlMap = urlMapper.selectByShortCode(shortCode);
longUrl = urlMap.getLongUrl();
redisTemplate.opsForValue().set("short:" + shortCode, longUrl, 3600, TimeUnit.SECONDS);
}
return longUrl;
}
// 3. 10进制转62进制
private static final String CHARS = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
private String base62Encode(long num) {
StringBuilder sb = new StringBuilder();
while (num > 0) {
sb.append(CHARS.charAt((int)(num % 62)));
num /= 62;
}
return sb.reverse().toString();
}
}
线上故障排查实战
案例:CPU 100% 排查
# 1. 查看进程 top -c # 找到PID # 2. 查看该进程的线程 top -Hp PID # 3. 将线程ID转为16进制 printf "%x\n" 线程ID # 4. 查看线程堆栈 jstack PID | grep 线程ID十六进制 -A 50 # 5. 常见原因: # - 死循环 # - 频繁GC # - 线程阻塞(等待锁/IO)
代码示例 - 死循环排查:
// 一旦线上CPU飙升,很可能有类似代码
public class CPUTrouble {
// 死循环示例
public void deadLoop() {
while (true) {
// 业务逻辑
}
}
// 正确的做法:加上超时控制
public void correctLoop() {
long start = System.currentTimeMillis();
while (System.currentTimeMillis() - start < 5000) { // 最多执行5秒
// 业务逻辑
}
}
}
最常问的第三问:Spring事务失效场景
@Service
public class TransactionDemo {
// 场景1:同类内部调用 - 事务失效
public void outerMethod() {
this.innerMethod(); // 这是直接调用,不走代理
}
@Transactional
public void innerMethod() {
// 数据库操作
}
// 解决:注入自身代理对象
@Autowired
private TransactionDemo self;
public void outerMethod2() {
self.innerMethod(); // 通过代理调用
}
// 场景2:final方法(CGLIB代理无法重写)或private方法
// 场景3:异常被捕获,未抛出
@Transactional
public void methodCatch() {
try {
int result = 1 / 0;
} catch (Exception e) {
// 异常被捕获,事务不会回滚
}
}
// 解决方法:抛异常
@Transactional
public void methodThrow() {
try {
int result = 1 / 0;
} catch (Exception e) {
throw new RuntimeException("异常", e); // 抛出RuntimeException
}
}
// 场景4:传播行为不当
// Propagation.NOT_SUPPORTED 不会启动事务
// 场景5:配置了错误的回滚条件
// @Transactional(rollbackFor = Exception.class) // 必须指定,否则只回滚RuntimeException
// 场景6:数据库引擎不支持事务(MyISAM)
}
线程池面试必问
public class ThreadPoolDemo {
// 问题1:为什么不用Executors.newFixedThreadPool?
// 1. 无界队列(LinkedBlockingQueue),OOM风险
// 2. 线程数量固定,无法灵活伸缩
// 正确方式:
@Bean
public ThreadPoolExecutor businessThreadPool() {
return new ThreadPoolExecutor(
10, // 核心线程数
20, // 最大线程数
60, // 空闲时间
TimeUnit.SECONDS,
new ArrayBlockingQueue<>(100), // 有界队列,容量100
new NamedThreadFactory("business-"),
new ThreadPoolExecutor.CallerRunsPolicy() // 拒绝策略
);
}
// 问题2:线程池执行流程
// 提交任务 → 核心线程数不足?→ 创建核心线程执行
// → 核心线程满了?→ 放入队列
// → 队列满了?→ 创建非核心线程
// → 最大线程满了?→ 执行拒绝策略
// 问题3:常见拒绝策略
// ThreadPoolExecutor.AbortPolicy:直接抛异常(默认)
// DiscardPolicy:丢弃任务不抛异常
// DiscardOldestPolicy:丢弃最旧的任务(队列第一个)
// CallerRunsPolicy:调用者线程执行(不会丢任务,但会阻塞调用者)
}
MySQL索引优化实战
-- 最左匹配原则示例 CREATE INDEX idx_user_name_age ON t_user(name, age); -- 下面的SQL会用到索引 SELECT * FROM t_user WHERE name = '张三'; -- 用索引 SELECT * FROM t_user WHERE name = '张三' AND age = 18; -- 用索引 -- 下面的SQL不会用到索引 SELECT * FROM t_user WHERE age = 18; -- 跳过第一个字段,不走索引 -- 覆盖索引优化 -- 原SQL(回表查询慢) SELECT * FROM t_order WHERE user_id = 100; -- 优化为覆盖索引 CREATE INDEX idx_order_user_status ON t_order(user_id, status); SELECT user_id, status FROM t_order WHERE user_id = 100; -- 只查索引列,避免回表 -- 分页优化 -- 深度分页(慢) SELECT * FROM t_order ORDER BY id LIMIT 100000, 20; -- 优化:延迟关联 SELECT * FROM t_order WHERE id > (SELECT id FROM t_order ORDER BY id LIMIT 100000, 1) ORDER BY id LIMIT 20;
消息队列可靠性保障
@Component
public class MQProducter {
// 问题:如何保证消息不丢失?
// 发送端:
@Autowired
private RabbitTemplate rabbitTemplate;
public void sendOrderMessage(Order order) {
CorrelationData correlationData = new CorrelationData(order.getId());
// 开启confirm模式:发送成功后回调确认
rabbitTemplate.convertAndSend(
"order.exchange",
"order.route",
order,
correlationData
);
}
@PostConstruct
public void init() {
// Confirm确认回调
rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
if (!ack) {
// 消息发送失败,重试或入库
System.err.println("消息发送失败: " + cause);
}
});
}
// 消费端:手动ACK
@RabbitListener(queues = "order.queue")
public void consume(Order order, Channel channel, @Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
try {
// 处理业务
orderService.handleOrder(order);
// 手动确认
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 处理失败,要求重试或进入死信队列
channel.basicNack(deliveryTag, false, true); // 重新入队
}
}
}
系统设计真题
设计一个秒杀系统
// 架构层次:
// 1. 前端层:按钮置灰 + 答题 + 限流(滑动窗口)
// 2. 网关层:负载均衡 + 限流
// 3. 应用层:分布式锁 + 库存预减
// 4. 数据层:Redis库存预热 + 异步下单
@Service
public class SeckillService {
// Redis预减库存
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Autowired
private RocketMQTemplate rocketMQTemplate;
// 商品数量预先加载到Redis
public void preLoadStock(Long productId, int count) {
redisTemplate.opsForValue().set("seckill:stock:" + productId, String.valueOf(count));
}
// 秒杀入口
public Result seckill(Long userId, Long productId) {
// 1. 限流:redis计数器
// 2. 预减库存(原子操作)
Long stock = redisTemplate.opsForValue()
.decrement("seckill:stock:" + productId);
if (stock < 0) {
// 库存不足,恢复数量
redisTemplate.opsForValue().increment("seckill:stock:" + productId);
return Result.error("已售罄");
}
// 3. 发送MQ异步处理订单
SeckillMessage message = new SeckillMessage(userId, productId);
rocketMQTemplate.convertAndSend("seckill-topic", message);
return Result.success("排队中");
}
// MQ消费者:真正落库处理
@RocketMQMessageListener(topic = "seckill-topic", consumerGroup = "seckill-group")
public class SeckillConsumer implements RocketMQListener<SeckillMessage> {
@Override
public void onMessage(SeckillMessage message) {
// 1. 创建订单(唯一索引防重复)
// 2. 扣减数据库库存
// UPDATE stock SET count = count - 1 WHERE product_id = ? AND count > 0
// 3. 发送成功通知
}
}
}
消息队列必答 - Kafka/RabbitMQ对比
// 面试官:说一下Kafka和RabbitMQ的区别和选型 面试要点: 1. 吞吐量:Kafka(百万级/秒) > RabbitMQ(万级/秒) 2. 消息顺序:Kafka分区内有序;RabbitMQ需要特殊配置 3. 消息确认:Kafka offset机制;RabbitMQ手动ACK 4. 延迟:Kafka毫秒级;RabbitMQ微秒级 5. 功能特性:RabbitMQ功能丰富(延迟、死信、优先级);Kafka简单 6. 扩展性:Kafka水平扩展好(分区机制) 选型建议: - 需要高吞吐、日志收集 → Kafka - 业务复杂、需精确路由 → RabbitMQ - 延迟敏感业务 → RabbitMQ
十一、JVM调优实战
// 线上OOM排查案例
public class OOMAnalyze {
// 出现OOM后:
// 命令添加参数:
// -XX:+HeapDumpOnOutOfMemoryError
// -XX:HeapDumpPath=/tmp/heapdump.hprof
// 分析堆转储文件
// jmap -dump:format=b,file=/tmp/heap.hprof PID
// 使用MAT分析:
// - 找大对象
// - 找重复字符串
// - 找未释放的集合
// 常见OOM场景:
// 1. 堆内存不足(对象过多)
// 2. 元空间不足(动态生成类)
// 3. 直接内存(NIO使用不当)
}
十二、Redis高级特性必答
// 面试官:Redis中热Key和大Key如何解决? // 热Key问题: // 1. 本地缓存:JVM层缓存热点数据 // 2. 多副本:多个Redis副本分担读压力 // 3. 读写分离:master写,slave读 // 大Key问题: // 1. 拆分:将大对象拆分成多个key // 2. 压缩:序列化时使用压缩算法(protobuf、snappy) // 3. 分批:删除大集合时用scan而非del // Sorted Set底层实现(树和跳跃表的选择原因) // 综合对比:跳跃表实现简单、查找效率低,但范围查找效率高 // 因此Redis选择跳表 + 哈希表 // 一致性哈希在Redis中的应用: // 一致性哈希解决分布式缓存中节点的动态增删问题 // 虚拟节点解决数据倾斜问题
十三、Spring Boot + MyBatis-Plus经典案例
// 实现多租户数据隔离
@Configuration
public class TenantConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new TenantLineInnerInterceptor(
new TenantLineHandler() {
@Override
public Expression getTenantId() {
// 从上下文获取租户ID
return new LongValue(TenantContext.getTenantId());
}
@Override
public String getTenantIdColumn() {
return "tenant_id"; // 自动拼接tenant_id条件
}
}
));
return interceptor;
}
}
// 分页插件
@Configuration
public class PaginationConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
return interceptor;
}
}
十四、面试中要掌握的框架原理
Spring Boot自动配置原理
面试回答思路:
1. @SpringBootApplication = @Configuration + @EnableAutoConfiguration + @ComponentScan
2. @EnableAutoConfiguration 通过 @Import(AutoConfigurationImportSelector.class)
3. 加载 META-INF/spring.factories 中所有自动配置类
4. 结合 @ConditionalOnXxx 条件判断哪些配置生效
5. 自动配置类中通过 @Bean 生成对应的 Bean
Spring循环依赖解决方案
// 面试句重点:
// 三级缓存:
// 一级缓存: singletonObjects 存储完整Bean
// 二级缓存: earlySingletonObjects 存储半成品Bean(未填充属性)
// 三级缓存: singletonFactories 存储ObjectFactory(lambda表达式)
@Lazy // 最简单的解决方案:懒加载打破循环
public class A {
@Autowired
private B b;
}
// 循环依赖无法解决的情况(完全类比构造函数循环依赖)
MyBatis一级缓存和二级缓存
一级缓存:SqlSession级别,默认开启,同一个SqlSession查询会命中缓存
二级缓存:namespace级别,需要配置,且实体类需要序列化
注意:多表关联查询时缓存可能导致脏数据
十五、面试中的高并发实战案例
案例:热搜榜设计
// 问题:如何实现热搜排行榜?
// 方案:利用Redis的ZSet结构
public class HotSearchService {
@Autowired
private RedisTemplate<String, String> redisTemplate;
private static final String HOT_KEY = "hot:search";
// 1. 搜索时增加热度
public void addHot(String keyword) {
redisTemplate.opsForZSet().incrementScore(HOT_KEY, keyword, 1.0);
}
// 2. 获取Top10热搜
public List<String> getTop10() {
Set<String> top = redisTemplate.opsForZSet()
.reverseRange(HOT_KEY, 0, 9); // 分数从高到低
return new ArrayList<>(top);
}
// 3. 热度随时间衰减
// 可以使用定时任务:每小时把所有词的分数乘以0.9
// 4. 防止某个词在某个时间段被重复刷
// 可加上单日搜索量限制
}
面试拿到Offer的关键
| 要素 | 重要性 | 怎么准备 |
|---|---|---|
| 基础功底 | 多线程、集合、JVM原理必须烂熟于心 | |
| 框架原理 | 能讲出Spring/MyBatis核心原理 | |
| 系统设计 | 面试前准备5-8个业务场景 | |
| 实战经验 | 独立完成至少2-3个项目,深入理解每一行代码 | |
| 思路清晰 | 多练习,用金字塔原理回答,先说结论再说原因 |
面试禁忌
- 不要背答案:结合自己的项目去阐述,哪怕是实习项目
- 不要说"我不会":尽量说"这块我了解的是…"
- 不要一直强调不会的:引导面试官问你擅长的领域
- 不要紧张:提前做几轮模拟面试
最后的考前面试清单
- [ ] 把HashMap、ConcurrentHashMap源码看一遍
- [ ] 能默写线程池的7个参数并解释执行流程
- [ ] Spring IOC/AOP源码核心流程过一遍
- [ ] MySQL索引结构(B+树)能画出来并讲清楚
- [ ] Redis数据类型及典型应用场景
- [ ] 准备2-3个系统设计案例(秒杀、分布式锁、限流)
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播