Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/svg/2.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
Java加速进程/线程_Java_Multithreading - Fatal编程技术网

Java加速进程/线程

Java加速进程/线程,java,multithreading,Java,Multithreading,我有一个相当大的数组列表 我必须检查每一个指数,做一个昂贵的计算 我的第一个想法是把它放到一个线程中。 它可以工作,但仍然非常缓慢。我在计算过程中做了一些修改,以降低成本,但计算速度仍然很慢。我想出的最好的解决方案基本上就是这个 public void calculate(){ calculatePart(0); calculatePart(1); } public void calculatePart(int offset) { new Thread() {

我有一个相当大的数组列表

我必须检查每一个指数,做一个昂贵的计算

我的第一个想法是把它放到一个线程中。 它可以工作,但仍然非常缓慢。我在计算过程中做了一些修改,以降低成本,但计算速度仍然很慢。我想出的最好的解决方案基本上就是这个

public void calculate(){
    calculatePart(0);
    calculatePart(1);
}

public void calculatePart(int offset) {
      new Thread() {
            @Override
            public void run() { 
                int i = offset;
                 while(arrayList.size() > i) {
                    //Do the calulation
                     i +=2;
              }
          }              
     }.start();
}

然而,这感觉像是一个懒惰、不专业的解决方案。这就是为什么我要问,从理论上讲,是否有更干净、更快的解决方案: 如果您有X个元素,并且您的计算必须对每个元素执行N个操作,那么 您的计算机(处理器)总共必须执行X*N操作,然后

只有在线程等待时(例如,文件或网络操作),计算操作中存在一些并行线程时,并行线程才能使计算速度更快。这段时间可以被其他线程使用。但如果所有操作都是纯CPU(例如数学)且线程没有等待,则执行X*N操作所需的时间保持不变

此外,每个线程都必须赋予其他线程在某个时刻控制CPU的能力。它会在方法调用之间自动发生,或者如果代码中有
Thread.yield()
调用,则会自动发生

例如,方法如下:

public void run()
{
  long a=0;
  for (long i=1; i < Long.MAX_VALUE; i++)
  {
   a+=i;
  }
 }
public void run()
{
长a=0;
对于(长i=1;i

在CPU完全完成并退出之前,不会给其他线程控制CPU的机会

假设在每个元素上执行任务不会导致数据竞争,您可以利用并行性的强大功能。为了最大化同时发生的计算数量,您必须将任务分配给系统中可用的每个处理器

在Java中,您可以通过以下方式获得可用的处理器(核心)数量:

int parallelism = Runtime.getRuntime().availableProcessors();
其思想是创建与可用处理器数量相等的线程

因此,如果您有4个可用的处理器,您可以创建4个线程,并要求它们以4的间隔处理项目。假设您有一个大小为10的列表,需要并行处理

那么

线程1处理索引为0,4,8的项
线程2处理索引1,5,9处的项目
线程3处理索引2,6处的项目
线程4处理索引3,7处的项

我尝试用以下代码模拟您的场景:

import java.util.Arrays;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

public class SpeedUpTest {

    public static void main(String[] args) throws InterruptedException, ExecutionException {
        long seqTime, twoThreadTime, multiThreadTime;
        List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);

        long time = System.currentTimeMillis();
        sequentialProcessing(list);
        seqTime = System.currentTimeMillis() - time;

        int parallelism = 2;
        ExecutorService executorService = Executors.newFixedThreadPool(parallelism);
        time = System.currentTimeMillis();
        List<Future> tasks = new ArrayList<>();
        for (int offset = 0; offset < parallelism; offset++) {

            int finalParallelism = parallelism;
            int finalOffset = offset;
            Future task = executorService.submit(() -> {
                int i = finalOffset;
                while (list.size() > i) {
                    try {
                        processItem(list.get(i));
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    i += finalParallelism;
                }
            });
            tasks.add(task);
        }
        for (Future task : tasks) {
            task.get();
        }
        twoThreadTime = System.currentTimeMillis() - time;

        parallelism = Runtime.getRuntime().availableProcessors();
        executorService = Executors.newFixedThreadPool(parallelism);
        tasks = new ArrayList<>();
        time = System.currentTimeMillis();
        for (int offset = 0; offset < parallelism; offset++) {

            int finalParallelism = parallelism;
            int finalOffset = offset;
            Future task = executorService.submit(() -> {
                int i = finalOffset;
                while (list.size() > i) {
                    try {
                        processItem(list.get(i));
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    i += finalParallelism;
                }
            });
            tasks.add(task);
        }
        for (Future task : tasks) {
            task.get();
        }
        multiThreadTime = System.currentTimeMillis() - time;
        log("RESULTS:");
        log("Total time for sequential execution : " + seqTime / 1000.0 + " seconds");
        log("Total time for execution with 2 threads: " + twoThreadTime / 1000.0 + " seconds");
        log("Total time for execution with " + parallelism + " threads: " + multiThreadTime / 1000.0 + " seconds");


    }

    private static void log(String msg) {
        System.out.println(msg);
    }

    private static void processItem(int index) throws InterruptedException {
        Thread.sleep(5000);
    }

    private static void sequentialProcessing(List<Integer> list) throws InterruptedException {

        for (int i = 0; i < list.size(); i++) {
            processItem(list.get(i));
        }
    }

}
导入java.util.array;
导入java.util.ArrayList;
导入java.util.List;
导入java.util.concurrent.ExecutionException;
导入java.util.concurrent.ExecutorService;
导入java.util.concurrent.Executors;
导入java.util.concurrent.Future;
公共级加速测试{
公共静态void main(字符串[]args)引发InterruptedException、ExecutionException{
长seqTime、twoThreadTime、多线程时间;
List=Arrays.asList(1,2,3,4,5,6,7,8,9,10);
长时间=System.currentTimeMillis();
顺序处理(列表);
seqTime=System.currentTimeMillis()-时间;
int并行度=2;
ExecutorService ExecutorService=Executors.newFixedThreadPool(并行);
时间=System.currentTimeMillis();
列表任务=新建ArrayList();
对于(int offset=0;offset{
int i=最终偏移量;
while(list.size()>i){
试一试{
processItem(list.get(i));
}捕捉(中断异常e){
e、 printStackTrace();
}
i+=最终平行性;
}
});
任务。添加(任务);
}
用于(未来任务:任务){
task.get();
}
twoThreadTime=System.currentTimeMillis()-时间;
并行度=Runtime.getRuntime().availableProcessors();
executorService=Executors.newFixedThreadPool(并行性);
tasks=newarraylist();
时间=System.currentTimeMillis();
对于(int offset=0;offset{
int i=最终偏移量;
while(list.size()>i){
试一试{
processItem(list.get(i));
}捕捉(中断异常e){
e、 printStackTrace();
}
i+=最终平行性;
}
});
任务。添加(任务);
}
用于(未来任务:任务){
task.get();
}
多线程时间=System.currentTimeMillis()-时间;
日志(“结果:”);
日志(“顺序执行的总时间:“+seqTime/1000.0+”秒”);
日志(“使用2个线程执行的总时间:“+twoThreadTime/1000.0+”秒”);
日志(“使用“+并行+”线程执行的总时间:“+多线程时间/1000.0+”秒”);
}
私有静态无效日志(字符串msg){
System.out.println(msg);
}
私有静态void processItem(int索引)引发InterruptedException{
睡眠(5000);
}
私有静态void sequentialProcessing(列表)抛出InterruptedException{
对于(int i=0;i
输出:

结果:

顺序执行的总时间:50.001秒

使用2个线程执行的总时间:25.102秒

使用4个线程执行的总时间:15.002秒


你到底在做什么样的计算?您是在对列表中的对象进行变异,还是在计算某些对象并将其存储在变量中?这与sp无关