Java 相当于D语言中的Executor服务?

Java 相当于D语言中的Executor服务?,java,d,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 (In

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,或者该功能在标准库中不可用。

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

基本上,您的代码将转换为:

foreach (f; files.parallel) {
    process(f); // or just paste what should be done with f in here if it matters
}
std.parallelism是多线程的高级实现。如果您只想拥有一个任务池,您可以创建一个
新任务池()
(可选参数为worker number),然后使用
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
函数。例如,您可以有一个文件加载队列任务,该任务始终使用receive等待,并且当UI将文件放入加载队列(只需调用send一次或多次)时,它可以处理这些文件并将其发送回使用主循环中的超时接收的UI任务

std.concurrency
还有一个
FiberScheduler
,可用于在单个线程中进行线程式编程。例如,如果您有一个UI,它可以进行绘图和输入处理以及各种各样的事情,那么在主循环中,每次勾选时都会调用FiberScheduler,并且当前运行的所有任务都将在上次停止的位置继续(通过调用
yield
)。当您有一个需要很长时间才能生成的图像生成器时,这非常有用,但您不想将UI阻塞太久,因此每次迭代都调用
yield()
来停止生成器的执行并执行主循环的一个步骤


当光纤不运行时,它们甚至可以在线程之间传递,这样您就可以从std.parallelism和自定义FiberScheduler实现中获得一个线程池,并进行负载平衡,例如,这在web服务器中可能很有用

如果要在不使用FiberScheduler的情况下创建光纤并将其称为raw(并检查其完成状态并将其从任何自定义调度器实现中删除),则可以从
core.thread
继承
Fiber
类,该类的工作原理与线程完全相同,只需调用Fiber.yield()每次您等待或认为自己处于CPU密集型区域时

虽然因为大多数API不是为光纤制作的,它们会阻塞光纤,使光纤看起来有点无用,所以您一定要使用一些使用光纤的API。例如,vibe.d有很多基于光纤的函数,但是有一个定制的std.concurrency实现,所以您需要注意这一点

但回到您的问题,您需要的是
任务池
或在您的特定情况下的
并行
功能


“当光纤不运行时,它们甚至可以在线程之间传递”,我在哪里可以找到这方面的信息?我认为光纤不能传递给其他线程。@Patric“相反,光纤可以在线程之间自由传递,只要它们当前未执行。”