# 问题和练习的答案:并发
# 问题
- 你可以传递一个 Thread 对象 Executor.execute 吗?这样的调用是否有意义? - Thread实现了 Runnable 接口,这样你就可以通过 Executor.execute 执行- Thread实例。 但是,以- Thread这种方式使用对象是没有意义的。如果对象直接实例化- Thread,其 run 方法不执行任何操作。 您可以继承- Thread并重写- run方法定义一个子类,但是这样一个类将实现执行器不会使用的功能。
# 练习
- 以下代码怎么修改才能让主线程中的 message 始终都赋值成功,且打印出来?是否可以调整两个 - sleep的参数?如何保证始终都有效?- 解决方案: 程序几乎总是打印:"Mares do eat oats." 但是这个结果并不能保证,因为 两个修改语句之间没有发生关系。有两种方法可以保证: - 在主线程中,保留对 CorrectorThread 实例的引用。然后 join
 - CorrectorThread correctorThread = new CorrectorThread(); correctorThread.start(); correctorThread.join(); message = "Mares do not eat oats."; System.out.println(message);1
 2
 3
 4
 5- 封装 message 在具有同步方法的对象中。message 除了通过这些方法外,不要参考。
 - 这两种技术都建立了 - happens-before的关系,使得 message 可见的变化。- 第三种技术是简单地声明 message 为 volatile。它们可能会顺序发生,但是由于调度的不确定性和未知的粒度 sleep,这是不能保证的。 - 改变两个 sleep 调用的参数也没有帮助,因为这并不能保证在关系之前发生。 
- 修改 守护块 中的生产者 - 消费者示例,以使用标准库类而不是 - Drop类
解决方案:
java.util.concurrent.BlockingQueue 接口定义了 get 阻塞队列为空,以及阻止队列已满的 put 方法。
这些是有效的定义的操作 Drop 除了 Drop 不是队列! 所以在前面的例子中,直接把 Drop 换成 BlockingQueue 即可
BlockingQueue 几乎是 Drop 一个替代品。在主要的问题是 Producer,随着 BlockingQueue 中,put 和 get 方法抛出 InterruptedException。
这意味着现有的 try 必须向上移动一个级别: