JVM在并行处理方面有多好?我什么时候应该创建自己的Threads和Runnables?为什么线程会干扰?

hor*_*irs 4 java multithreading multicore

我有一个运行许多小模拟的Java程序.它运行遗传算法,其中每个适应度函数是使用每个染色体上的参数的模拟.如果单独运行,每个人大约需要10秒左右,我想要运行一个相当大的人口规模(比如100?).在上一次模拟完成之前,我无法开始下一轮模拟.我可以访问一台有很多处理器的机器,我想知道我是否需要做任何事情来使模拟并行运行.我之前从未为多核处理器明确写过任何内容,我理解这是一项艰巨的任务.

所以这就是我想知道的:JVM并行化的程度和程度如何?我已经读过它创建了低级别的线程,但它有多聪明?效率如何?如果我将每个模拟作为线程,我的程序会运行得更快吗?我知道这是一个很大的话题,但是你能否指出一些关于并行处理和Java的入门文献?

非常感谢!

更新: 好的,我已经实现了ExecutorService并使我的小模拟实现了Runnable并且有run()方法.而不是写这个:

Simulator sim = new Simulator(args); 
sim.play(); 
return sim.getResults(); 
Run Code Online (Sandbox Code Playgroud)

我在构造函数中写这个:

ExecutorService executor = Executors.newFixedThreadPool(32);
Run Code Online (Sandbox Code Playgroud)

然后每次我想在池中添加一个新的模拟时,我运行它:

RunnableSimulator rsim = new RunnableSimulator(args); 
exectuor.exectue(rsim); 
return rsim.getResults(); 
Run Code Online (Sandbox Code Playgroud)

RunnableSimulator::run()方法调用该Simulator::play()方法,既没有参数.

我想我正在受到线程干扰,因为现在模拟错误了.错误输出我的意思是变量包含他们真正不应该的值.模拟中的代码没有被更改,并且在模拟完成许多不同的参数之前.SIM卡的工作方式如下:每次转动它都会给游戏块一个循环,并在游戏板上的所有位置循环.它会检查给定的位置是否有效,如果是,则提交该块,并测量该板的优点.现在,显然无效的位置被传递给commit方法,从而导致整个地方的索引越界错误.

每个模拟都有自己的对象吗?基于上面的代码?我可以将完全相同的参数集传递给RunnableSimulatorSimulator类,而runnable版本将抛出异常.您认为可能导致这种情况,我该怎么做才能防止这种情况发生?我可以在新问题中提供一些代码示例来帮助吗?

Ada*_*icz 11

Java并发教程

如果你只是将一堆东西发送到不同的线程,并且它不会在不同的线程之间来回交谈,那就不是太难了; 只需在Runnable中写入每个并将它们传递给ExecutorService.

您应该浏览整个教程,但是对于这个特定的任务,请从这里开始.

基本上,你做这样的事情:

ExecutorService executorService = Executors.newFixedThreadPool(n);
Run Code Online (Sandbox Code Playgroud)

其中n是您想要一次运行的事物的数量(通常是CPU的数量).您的每个任务都应该是实现Runnable的对象,然后在ExecutorService上执行它:

executorService.execute(new SimulationTask(parameters...));
Run Code Online (Sandbox Code Playgroud)

Executors.newFixedThreadPool(n)将启动n线程,执行将把任务插入到这些线程的队列中.当任务完成时,它运行的线程不再繁忙,队列中的下一个任务将开始在其上运行.执行不会阻止; 它只会将任务放入队列并继续下一个任务.

需要注意的是,你真的不在任务之间共享任何可变状态.您的任务类不应该依赖于将在它们之间共享的任何可变内容(即静态数据).有办法处理共享可变状态(锁定),但如果你可以完全避免这个问题,那将会容易得多.

编辑:阅读你的问题的编辑,看起来你真的想要一些不同的东西.而不是实施Runnable,实施Callable.您的call()方法应与您当前的方法几乎相同run(),除非它应该return getResults();.然后,submit()它到你的ExecutorService.您将得到一个Future回报,您可以使用它来测试模拟是否完成,并且当它完成时,获得结果.