threadpool—如何避免java executorservice中的上下文切换

46qrfjad  于 2021-07-13  发布在  Java
关注(0)|答案(0)|浏览(204)

我使用一个软件(anylogic)导出可运行的jar文件,这些文件本身使用不同的参数重复运行一组模拟(所谓的参数变化实验)。我正在运行的模拟具有非常高的ram密集度,因此我必须限制jar文件可用的内核数量。在anylogic中,可用内核的数量很容易设置,但是通过服务器上的linux命令行,我知道的唯一方法是使用 taskset 命令手动指定要使用的可用内核(使用cpu关联“掩码”)。到目前为止,这已经很好地工作了,但是由于您必须指定要使用的各个核心,因此我了解到,根据您选择的核心,性能可能会有相当大的差异。例如,您可能希望最大限度地利用cpu缓存级别,因此如果选择共享过多缓存的内核,则性能会降低很多。
因为anylogic是用java编写的,所以我可以使用java代码来指定模拟的运行。我正在考虑使用javaexecutorservice构建一个单独运行的池,这样我就可以将池的大小指定为与我正在使用的机器的ram相匹配的核数。我认为这会带来很多好处,最重要的是,也许计算机的scehduler可以更好地选择内核以最小化运行时间。
在我的测试中,我构建了一个小的anylogic模型,运行大约需要10秒(它只是在两个状态图状态之间反复切换)。然后我用这个简单的代码创建了一个定制的实验。

ExecutorService service = Executors.newFixedThreadPool(2);

for (int i=0; i<10; i++)
{
    Simulation experiment = new Simulation();
    experiment.variable = i;
    service.execute( () -> experiment.run() );
}

我希望看到的是只有2个 Simulation 对象一次启动,因为这是线程池的大小。但我看到所有10个线程都启动并在2个线程上并行运行。这让我觉得上下文转换正在发生,我认为这是非常低效的。
什么时候,而不是调用anylogic Simulation ,我只是在 service.execute 功能,似乎工作正常,显示只有2个 Tasks 一次跑步。

public class Task implements Runnable, Serializable {

    public void run() {
        traceln("Starting task on thread " + Thread.currentThread().getName());
        try {
            TimeUnit.SECONDS.sleep(5);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        traceln("Ending task on thread " + Thread.currentThread().getName());
    }
}

有人知道为什么anylogic函数会同时设置所有的模拟吗?

暂无答案!

目前还没有任何答案,快来回答吧!

相关问题