将for循环分离为多线程Java
我必须用Java做一个蒙特卡罗模拟。我的情况如下:将for循环分离为多线程Java,java,multithreading,parallel-processing,Java,Multithreading,Parallel Processing,我必须用Java做一个蒙特卡罗模拟。我的情况如下: for(int w=0;w
for(int w=0;w
其中,n
趋向于大-真的大(数以百万计)。此外,t
和a
循环(以及内部计算)独立于w
循环(我使用w
循环重复矩阵计算n次)。这意味着,我并不真正关心在之前或之后运行哪个w
是否有一种方法(可能不复杂,因为我从未使用过并行编程)来拆分外部for循环,并使用不同的线程同步执行(例如,如果我使用所有线程而不是一个线程运行四核处理器)
在@tevemadar solution之后编辑
据我所知,我可以这样做:
公共级MyMonteCarloClass{
私有静态双精度[][]蒙特卡洛斯=新双精度[20][25];
随机生成器=新随机();
私有void incrementSum(){
对于(int t=0;t<25;t++){
对于(int a=0;a<20;a++){
monteCarloSums[a][t]+=generator.nextGaussian();
}
}
}
public double[]getValue(int numberOfSim){
IntStream.range(0,numberOfSim.parallel().forEach(I->incrementSum());
把这个还给我,monteCarloSums
}
}
对于三个嵌套循环,这样的速度会加快吗?使用队列并行执行Runables。可以使用Executors实用程序类创建的简单ThreadPoolExecutor
Executor executor = Executors.newFixedThreadPool(10); // 10 = number of threads
for (int w = 0; w < n; w++) {
final int w_final = w;
executor.execute(() -> {
for (int t = 0; t < 25; t++) {
for (int a = 0; a < 20; a++) {
// ...calculations...
// w_final instead of w here
}
}
});
}
Executor Executor=Executors.newFixedThreadPool(10);//10=螺纹数
对于(int w=0;w{
对于(int t=0;t<25;t++){
对于(int a=0;a<20;a++){
//…计算。。。
//w_final而不是这里的w
}
}
});
}
您希望利用可用于复杂计算的计算能力,这是一种有效的方案
多线程优化了系统资源的使用并提高了性能。宝贵的CPU时间不会被阻塞线程浪费,而是被其他线程用于执行所需的计算
但是没有正确性的并发是没有任何意义的。为了获得正确的结果,您可能需要同步并行计算(如果这些计算是相互关联的)
由于您是java并发的新手,我建议您使用Executor框架
该框架包括三个主要接口Executor、ExecutorService和ThreadPoolExecutor,它们抽象出了线程的大部分复杂性,并提供了执行和管理线程生命周期的高级方法
让我们从一个非常基本的解决方案开始,然后您可以根据自己的需求进行改进
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
public class WorkDistributer {
private static int THREAD_COUNT = 8;
public static void main(String... args) {
try {
final ExecutorService executor = Executors.newFixedThreadPool(THREAD_COUNT);
int n = Integer.MAX_VALUE;
for (int w = 0; w < n; w++) {
executor.execute(new Worker());
}
executor.awaitTermination(5, TimeUnit.MINUTES);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
class Worker implements Runnable {
@Override
public void run() {
for (int t = 0; t < 25; t++) {
for (int a = 0; a < 20; a++) {
// System.out.println("Doing calculation....");
}
}
}
}
导入java.util.concurrent.ExecutorService;
导入java.util.concurrent.Executors;
导入java.util.concurrent.TimeUnit;
公共类工作分发器{
私有静态int线程计数=8;
公共静态void main(字符串…参数){
试一试{
final ExecutorService executor=Executors.newFixedThreadPool(线程计数);
int n=整数的最大值;
对于(int w=0;w
注:
在这里,我们没有实现同步机制,但您可能需要根据您的要求
根据系统配置调整线程数。在我的系统上,我有4个核心和8个逻辑处理器,我能够使用8个线程实现100%的利用率
使用IntStream
您可以轻松重写“经典”计数循环
for(int i=0;i<10;i++) {
System.out.print(i);
}
它们都将打印0123456789
然后可以并行处理流:
IntStream.range(0, 10).parallel().forEach(i->{
System.out.print(i);
});
它会突然产生一个混合顺序,比如6589724310
。所以它是并行运行的,您不必处理线程、执行器、任务等等
不过,你必须处理好几件事:
- 就像匿名内部类中的方法一样,lambda函数只能从外部作用域访问“有效的最终”变量。所以如果你有
intj=0
在循环前面,不能写入j=1代码>在循环中。但是您可以更改对象成员和数组项(因此j.x=1;
或j[0]=1;
可以工作)
- 您提到了蒙特卡罗,所以可能值得指出的是,随机数生成器并不是并行访问的忠实粉丝。有一个
ThreadLocalRandom.current()
调用,它会为您提供一个随机数生成器
- 另外,您肯定是在某处收集结果,当您明确指出大型
n
不用于任何用途时,请记住,多个线程可能会尝试更新收集器数组/对象的单个位置,这可能是问题,也可能不是问题
您尝试过使用线程吗?这些有帮助吗?并尝试在Internet上搜索java并行Intstream谢谢大家@abra的建议似乎真的很有用!非常感谢你!!!我还有一个问题,这是问题中的“编辑”标志(我不能在评论中写出来)@tevemadar@YodaAndFriends这个新问题应该作为一个新问题发布。这是一个基本的概念
IntStream.range(0, 10).parallel().forEach(i->{
System.out.print(i);
});