Есть ли что-нибудь в Java близко к параллельным коллекциям в Scala? - PullRequest
5 голосов
/ 25 июля 2011

Какой самый простой способ реализовать параллельные вычисления (например, на многоядерном процессоре) с использованием Java. И.Е. Java-эквивалент этого кода Scala

val list = aLargeList
list.par.map(_*2)

Существует эта библиотека , но она кажется подавляющей.

Ответы [ 4 ]

7 голосов
/ 25 июля 2011

http://gee.cs.oswego.edu/dl/jsr166/dist/extra166ydocs/

Не сдавайся так быстро , мгновенно!))

Из javadocs (с изменениями в карте к вашему f) сущность действительно такова:

ParallelLongArray a = ... // you provide
a.replaceWithMapping (new LongOp() { public long op(long a){return a*2L;}};);

в значительной степени так, верно?

val list = aLargeList
list.par.map(_*2)

& Если вы хотите жить с немного меньшей краткостью, вышеприведенное может быть достаточно чистым и понятным 3-строчным (и, конечно, если вы повторно используете функции, то это точно так же, какScala - встроенные функции.):

ParallelLongArray a = ... // you provide
LongOp f = new LongOp() { public long op(long a){return a*2L;}};
a.replaceWithMapping (f);

[отредактировано выше, чтобы показать краткую законченную форму, как вариант Scala OP] *

, и здесь она находится в максимально подробной форме, где мы начинаем с нуля для демонстрации:

import java.util.Random;
import jsr166y.ForkJoinPool;
import extra166y.Ops.LongGenerator;
import extra166y.Ops.LongOp;
import extra166y.ParallelLongArray;

public class ListParUnaryFunc {
    public static void main(String[] args) {

        int n = Integer.parseInt(args[0]);
        // create a parallel long array 
        // with random long values
        ParallelLongArray a =  ParallelLongArray.create(n-1, new ForkJoinPool());
        a.replaceWithGeneratedValue(generator);

        // use it: apply unaryLongFuncOp in parallel 
        //         to all values in array
        a.replaceWithMapping(unaryLongFuncOp);

        // examine it
        for(Long v : a.asList()){
            System.out.format("%d\n", v);
        }
    }

    static final Random rand = new Random(System.nanoTime());
    static LongGenerator generator = new LongGenerator() {
        @Override final
        public long op() { return rand.nextLong(); }
    };

    static LongOp unaryLongFuncOp = new LongOp() {
        @Override final public long op(long a) { return a * 2L; }
    };
}

Окончательное редактирование и примечания:

Также обратите внимание, что простой класс, такой как следующий (который вы можете повторно использовать в своих проектах):

/**
 * The very basic form w/ TODOs on checks, concurrency issues, init, etc.
 */
final public static class ParArray {
    private ParallelLongArray parr;
    private final long[] arr;
    public ParArray (long[] arr){
        this.arr = arr;
    }
    public final ParArray par() {
        if(parr == null)
            parr = ParallelLongArray.createFromCopy(arr, new ForkJoinPool()) ;
        return this;
    }
    public final ParallelLongArray map(LongOp op) {
        return parr.replaceWithMapping(op);
    }
    public final long[] values() { return parr.getArray(); }
}

и что-то подобное позволит вам писать более гибкий Java-код (если для вас важна краткость):

long[] arr = ... // you provide
LongOp f = ... // you provide

ParArray list = new ParArray(arr);
list.par().map(f);

И приведенный выше подход, безусловно, может быть продвинут, чтобы сделать его еще чище.

1 голос
/ 25 июля 2011

Сделать это на одной машине довольно легко, но не так просто, как это делает Scala. Та библиотека, которую вы разместили, уже отличается от Java 5 и выше. Вероятно, самая простая вещь для использования - это ExecutorService. Это представляет собой последовательность потоков, которые могут быть запущены на любом процессоре. Вы отправляете ему задачи, и эти вещи возвращают результаты.

http://download.oracle.com/javase/1,5.0/docs/api/java/util/concurrent/ThreadPoolExecutor.html

http://www.fromdev.com/2009/06/how-can-i-leverage-javautilconcurrent.html

Я бы предложил использовать ExecutorService.invokeAll (), который будет возвращать список фьючерсов. Затем вы можете проверить их, чтобы убедиться, что они сделаны.

Если вы используете Java7, вы можете использовать инфраструктуру fork / join, которая может сэкономить вам некоторую работу. С помощью всего этого вы можете создать что-то очень похожее на параллельные массивы Scala, поэтому использовать его довольно кратко.

0 голосов
/ 31 марта 2013

В Java 8 будет эквивалент: http://www.infoq.com/articles/java-8-vs-scala

0 голосов
/ 25 июля 2011

Используя потоки, в Java нет такого встроенного.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...