期货是否在单个线程上执行? (斯卡拉)

时间:2015-04-21 16:38:51

标签: multithreading scala concurrency htmlunit future

使用Scala中的默认隐式执行上下文,是否会在单个专用线程上计算每个新的未来,还是将计算划分并分发到线程池中的多个线程?

我不知道这是否有帮助,这个问题的背景是我想使用HtmlUnit API执行多个并发操作。为此,我将每个新的WebClient实例包装在Future中。唯一的问题是WebClient类不是线程安全的,所以我担心它可能会被分解并发送到不同的线程。

2 个答案:

答案 0 :(得分:15)

在一个线程上执行一个未来。可能会在多个线程上执行几个期货。因此,不超过一个未来可以同时占用一个线程。

它是如何工作的?当您创建Future时,它意味着您已将任务提交到您的线程池 - 这个任务不能被隐式并行化,因此它只在一个线程上执行。提交到池的一个或多个任务被放入池的队列中,因此执行器逐个从该队列中获取任务,并在一些随机(或有意)选择的线程上运行每个任务。因此,几个期货可能会涉及多个主题。

关于共享对象 - 对于期货之间共享的对象安全执行操作的唯一方法是使用Executors.newFixedThreadPool(1),它将仅使用整个池中的一个线程。另一个解决方案 - 是为每个未来克隆这样的对象。使用actor(使你的共享对象成为一个actor的状态)应该是最好的选择。

如果你每个未来都使用一个对象 - 一切都应该没问题。

注意:未来的处理程序(如Future{ ... }.map(handler))可能在与未来本身不同的线程中执行,但它实际上会创建另一个Future来获取结果。 flatMap也是如此。更确切地说,他们使用onComplete创建CallbackRunnable以在旧的未来成功之后启动处理程序(可能在不同的线程中) - 这个回调只是完成了新创建的未来,所以仍然“每个未来不超过一个线程”

答案 1 :(得分:-1)

Future[+T]无法保证如果它由多个期货组成,它将在同一个线程上完成。也就是说,它并不意味着您将获得并发修改异常或类似的东西。你仍然可以获得顺序执行的异步代码,在这种情况下它是安全的。

关于你的第二个问题,只要你每个未来都有一个实例,你就不应该有任何并发​​问题。