Java使用消息队列还是直接使用线程池ExecutorService异步处理？
说说这两种的区别，各自适合什么场景？
用线程池ExecutorService异步处理：我理解`ExecutorService`其实也是内部使用了队列（如`LinkedBlockingQueue`），所以从设计上，其实和使用中间价的消息队列是差不多一致的。只是这里应用服务器既充当生产者又充当消费者，也是消息队列中间价的实现者。这种应该适合非分布式的架构，比如简单的只有一台服务器。
使用消息队列：消息队列（指activeMQ，rabbitMQ，kafaKa，Redis等）因为一般都是中间件，部署在其他机器，需要一定的网络消耗。
本着解耦的目的，使用后者更合理，因为应用服务器一般内存也不会太多，队列长度不易太长。让应用服务器只处理逻辑比较合理。适合分布式架构。
1.使用`JDK`提供的异步框架`ExecutorService`。
```
threadPool.execute(new Runnable() {
    @Override
    public void run() {
        // 这里是异步处理的，比较耗时的逻辑，比如数据库操作
        userService.setDefaultAddressId(user.getUserId(), bookingForm.getAddressId());
    }
});
```
2.将消息发送到消息队列，如使用`redis`的`List`简单实现，然后后台线程消费消息。
```
// 生产消息
redisTemplate.opsForList().leftPush(LOG_MQ_KEY, JsonUtil.beanToJson(httpRequestLog));

// 后台线程异步消费消息
String popValue = redisTemplate.opsForList().rightPopAndLeftPush(LOG_MQ_KEY, TEMP_LOG_MQ_KEY);
```
MQ可以更加有扩展性, 支持的场景更多, 而且支持消息自动的持久化, 建议你看看 RabbitMQ 和 AMQP 协议, JMS 可以学但是没 AMQP 更加通用, redis的MQ还是不要用了, 那只是一个附带的功能, kafka 是大数据领域的不适合做核心业务功能, 只适合数据统计类应用的发送数据, 因为他不确保消息100%不丢失, 如此大的数据量丢一条无所谓的, 不会对统计结果造成影响, 但速度和吞吐量高很多
线程池就不一样了, 目前执行状态你无法知道, msg的消费率是多少都不知道, 消息转发啊, 消息拒绝啊, 都的自己实现, 而且是单机版的, 我目前用他来做一级转发, 就是用他来将 event 异步发送出去, 而不是让他异步做一些很繁重的工作, 举例: 
注册用户service方法, 当事务结束后, 发送 RegisterUserEvent, 这个发送就是用java线程池(如spring的), 然后 RegisterUserListener 监听到了这个 event 就发送 msg 到 Rabbit MQ, 之后对注册用户这个Topic感兴趣的应用都可以订阅, 比如送积分的服务, 送优惠券的服务, 开辟云盘空间的服务等等
java领域有很多这种类比, ehcache 和 redis对比做缓存啊, java并发库 和redis锁对比并发啊等等, 都可以提出你这类型的问题