适用于非线程安全代码的执行器

时间:2018-11-06 10:23:12

标签: java multithreading unit-testing executor

我正在使用线程池Executor开发一些最终将成为多线程的代码。线程池执行的任务将进行回调,并(有时)将其他任务提交给任务队列。我想先开发单线程代码,然后正确编写代码(我正在使用测试驱动开发),然后才进行修改,以确保线程安全(锁等)。为此,我需要一个Executor,可以安全地与非线程安全的代码一起使用。

思考,这意味着我需要一个单线程的Executor。也就是说,它导致所有工作都由调用线程完成。 JRE是否提供这样的Executor?还是可以将其Executor之一配置为在该模式下运行?


我已经在使用Humble Object测试模式来测试我的大多数单线程代码。但是,我的某些代码必须Executor或也许与ExecutorService交互,因为它与有关 scheduling并重新提交任务,并且它将以非平凡的方式完成。测试 代码是这里的挑战。这些任务将更新一个共享对象,该对象保留其结果和输入数据。我想推迟使共享库成为线程安全的,直到我实现并调试了调度和重新提交代码。

2 个答案:

答案 0 :(得分:2)

如果您打算首先开发一个单线程解决方案,而不是从Thread语义中抽象出业务逻辑,那是行之有效的方法。实施无需测试的CallableRunnable,而无需启动新的Thread,例如通过在单元测试中使用模拟的Executor

答案 1 :(得分:1)

如果代码确实仅需要{em> 一个Executor,而不是一个ExecutorService(更复杂),则很容易实现自己的单线程执行程序正是需要的。 Executor的API文档甚至向您展示了如何做到这一点:

class DirectExecutor implements Executor {
   public void execute(Runnable r) {
     r.run();
   }
}

如果代码确实需要ExecutorService,则可能Executors.newSingleThreadExecutor()提供的单线程执行程序足以测试非线程安全代码尽管产生的程序具有两个线程(运行单元测试的线程和ExecutorService的单个线程池线程)。这是因为ExecutorService必须提供以下thread-safety guarantees

  • Runnable提交CallableExecutorService任务之前在线程中执行的操作,在此任务执行的任何操作之前,< / li>
  • 然后依次通过Future.get()检索结果。
  • 先发生。

因此,如果运行单元测试的线程对所有提交的任务执行Future.get(),则所有共享对象的所有更改都将被安全发布,并且运行单元测试的线程可以安全地检查那些共享对象