Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/303.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
将for循环分离为多线程Java_Java_Multithreading_Parallel Processing - Fatal编程技术网

将for循环分离为多线程Java

将for循环分离为多线程Java,java,multithreading,parallel-processing,Java,Multithreading,Parallel Processing,我必须用Java做一个蒙特卡罗模拟。我的情况如下: for(int w=0;w

我必须用Java做一个蒙特卡罗模拟。我的情况如下:

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);
    });