相当于D语言中的ExecutorService?

时间:2017-10-29 23:10:59

标签: java d

D文档有点难以理解,如何在D?

中实现以下Java代码
ExecutorService service = Executors.newFixedThreadPool(num_threads);

for (File f : files) {
    service.execute(() -> process(f));
}

service.shutdown();
try {
    service.awaitTermination(24, TimeUnit.HOURS);
} catch (InterruptedException e) {
    e.printStackTrace();
}

我会使用std.parallelism还是std.concurrency,或者标准库中没有此功能。

1 个答案:

答案 0 :(得分:4)

您发布的示例最好由std.parallelism代表。您可以在其中使用parallel辅助函数,当在foreach中使用它时,它将自动在线程池中执行foreach循环的主体,其线程号(工作服大小)为totalCPUs - 1。您可以通过在执行任何并行代码之前设置defaultPoolThreads = x;来更改此默认值(最好在主开始时完成)或使用自定义taskPool。

基本上你的代码会转化为:

foreach (f; files.parallel) {
    process(f); // or just paste what should be done with f in here if it matters
}
std.parallelism是多线程的高级实现。如果您只想拥有一个任务池,可以创建一个new TaskPool()(将工作人员数作为可选参数),然后使用service.parallel(files)执行相同的操作。

或者,您可以使用

排队许多任务
foreach (f; files) {
    service.put!process(f);
}
service.finish(true); // true = blocking
// you could also do false here in a while true loop with sleeps to implement a timeout

然后允许实现超时。

虽然我建议使用parallel,因为它为你处理上面的代码+给每个线程一个存储来访问本地堆栈,所以你可以像普通的非并行foreach循环一样使用它。

文件的附注/说明:

std.concurrency也非常有用,但不是你的例子。在其中有一个spawn函数,它使用强大的消息传递API生成一个新线程。使用消息传递API(发送和接收),您可以在线程之间实现线程安全值传递,而无需使用套接字,文件或其他解决方法。

当你有一个任务(带有消息传递API的线程)并在其中调用receive时,它将等到传递的超时完成或另一个线程调用该任务的send函数。例如,您可以拥有一个文件加载队列任务,该任务总是等待使用接收,例如UI将文件放入加载队列(只需调用一次或多次发送),它可以处理这些文件并将它们发送回UI任务,该任务在主循环中使用超时接收。

std.concurrency也有FiberScheduler,可用于在单个线程中进行线程样式编程。例如,如果您有一个用于绘制和输入处理的UI以及各种事物,那么它可以在每个tick调用的主循环中完成,FiberScheduler和所有当前正在运行的任务将在上次停止的地方继续(通过调用{{1} })。当您有一个需要很长时间才能生成的图像生成器时,这很有用,但是您不想长时间阻止UI,因此每次迭代都会调用yield左右来停止生成器的执行并执行主循环的一步。

当光纤不运行时,它们甚至可以绕过线程传递,因此您可以从std.parallelism和自定义FiberScheduler实现获得一个线程池,并进行负载平衡,例如在Web服务器中这可能很有用。 / p>

如果您想在没有FiberScheduler的情况下创建Fibers并将其调用为原始(并检查其完成状态并从任何自定义调度程序实现中删除它们),您可以从yield()继承Fiber类,与Thread完全相同,每次等待或认为自己处于CPU密集型部分时,只需要调用Fiber.yield()。

虽然因为大多数API都不是为纤维制造的,但是它们会阻挡并使纤维看起来毫无用处,所以你肯定想要使用一些在那里使用纤维的API。例如,vibe.d有很多基于光纤的函数,但是有一个自定义的std.concurrency实现,所以你需要注意它。

但只是回到你的问题,core.thread或在你的特定情况下TaskPool函数是你需要的。

https://dlang.org/phobos/std_parallelism.html#.parallel https://dlang.org/phobos/std_parallelism.html#.TaskPool.parallel