首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >是否有一种简单的方法来并行化java中的foreach循环?

是否有一种简单的方法来并行化java中的foreach循环?
EN

Stack Overflow用户
提问于 2018-05-12 11:33:39
回答 3查看 1.7K关注 0票数 0

是否有一种简单的方法可以在java 8中使用一些库来并行一个foreach循环?

代码语言:javascript
运行
复制
void someFunction(SomeType stuff, SomeType andStuff) {
    for (Object object : lotsOfObjects)
        object.doSomethingThatCanBeDoneInParallel(stuff, andStuff);
}

多线程是有点痛苦和耗时,所以我想知道是否有一个更简单的方法来做上述使用某些库。

谢谢。

2018年6月3日编辑

ExecutorServices非常方便--事实上,我不能使用wait ()来等待,因为我运行每个帧并创建一个新的ExecutorServices --每个帧都太昂贵了。

最后,我写了一个类来并行一个fori循环,我想我和其他像我一样的新手分享它。

代码语言:javascript
运行
复制
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicBoolean;

public class ParallelForI {
    public ParallelForI(int numberOfThread) {
        NUMBER_OF_THREAD = numberOfThread;
        executorService = Executors.newFixedThreadPool(NUMBER_OF_THREAD);
        finished = new AtomicBoolean[NUMBER_OF_THREAD];
        for (int i = 0; i < finished.length; i++)
            finished[i] = new AtomicBoolean(true);
        // true is better for waitForLastRun before any run.
    }
    private ExecutorService executorService;
    private final int NUMBER_OF_THREAD;

    private AtomicBoolean[] finished;
    public void waitForLastRun() {
        synchronized (this) {
        /* synchronized outside the loop so other thread
         can't notify when it's not waiting. */
            for (int i = 0; i < NUMBER_OF_THREAD; i++) {
                if (!finished[i].get()) {
                    i = -1;
                    try {
                        this.wait(); //
                    } catch (InterruptedException e) {
                        // do nothing and move one.
                    }
                }
            }
        }
    }

    public void run(FunctionForI functionForI, final int MAX_I) {
        for (AtomicBoolean finished : finished)
            finished.set(false); // just started
        for (int i = 0; i < NUMBER_OF_THREAD; i++) {
            final int threadNumber = i;
            executorService.submit(new Runnable() {
                @Override // use lambda if you have java 8 or above
                public void run() {
                    int iInitial = threadNumber * MAX_I / NUMBER_OF_THREAD;
                    int iSmallerThan;
                    if (threadNumber == NUMBER_OF_THREAD - 1) // last thread
                        iSmallerThan = MAX_I;
                    else
                        iSmallerThan = (threadNumber + 1) * MAX_I / NUMBER_OF_THREAD;
                    for (int i1 = iInitial; i1 < iSmallerThan; i1++) {
                        functionForI.run(i1);
                    }
                    finished[threadNumber].set(true);
                    synchronized (this) {
                        this.notify();
                    }
                }
            });
        }
    }

    public interface FunctionForI {
        void run(int i);
    }
}

这就是使用它的方法:

代码语言:javascript
运行
复制
void someFunction(final SomeType stuff, final SomeType andStuff) {
    ParallelForI parallelForI = new parallelForI(numberOfThread);
    // swap numberOfThread with a suitable int

    parallelForI.run(new ParallelForI.FunctionForI() {
        @Override // use lambda if you have java 8 or above
        public void run(int i) {
            lotsOfObjects[i].doSomethingThatCanBeDoneInParallel(stuff, andStuff);
            // don't have to be array.
        }
    }, lotsOfObjects.length); // again, don't have to be array

    parallellForI.waitForLastRun(); // put this where ever you want 
    // You can even put this before parallelForI.run().
    // Although it doesn't make sense to do that...
    // Unlike shutdown() waitForLastRun() will not cause parallelForI to reject future task.
}
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2018-05-12 11:37:59

解决方案可以是启动Thread中的每个任务,如下所示:

代码语言:javascript
运行
复制
new Thread(() -> object.doSomethingThatCanBeDoneInParallel(stuff, andStuff)).start();

但是这不是一个相关的解决方案,因为创建线程成本很高,所以有一些机制和工具可以帮助您:构建一些Executors类的pools

一旦您有了将管理它的实例,就会为它提供任务,这些任务将在您选择的线程数上并行运行:

代码语言:javascript
运行
复制
void someFunction(SomeType stuff, SomeType andStuff) {
    ExecutorService exe = Executors.newFixedThreadPool(4);   // 4 can be changed of course
    for (Object object : lotsOfObjects) {
        exe.submit(() -> object.doSomethingThatCanBeDoneInParallel(stuff, andStuff));
    }

    // Following lines are optional, depending if you need to wait until all tasks are finished or not
    exe.shutdown();
    try {
        exe.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }   
}
票数 2
EN

Stack Overflow用户

发布于 2018-05-12 11:35:27

使用并行流。但这不是一个普遍的解决办法。

票数 1
EN

Stack Overflow用户

发布于 2018-05-12 11:38:04

java中的For循环本质上是串行的。没有办法对他们做这样的事。但是,通过引入流,可以使用它们对集合上的操作进行并行化。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/50305765

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档