Понимание многопоточности с циклом Java - PullRequest
1 голос
/ 20 апреля 2011

У меня есть код, который, я думаю, не может быть многопоточным, возможно, я ошибаюсь. Я хотел бы выполнить этот код в кластерной системе, но я не уверен, как его масштабировать для такого развертывания.

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

    public class Coord {
        public int a,b,c,d,e,f;


    public static void main(String[] args) throws IOException {
        FileOutputStream out = new FileOutputStream("/Users/evanlivingston/2b.txt");
        PrintStream pout = new PrintStream(out);
        Scanner sc = new Scanner(new File("/Users/evanlivingston/1.txt"));
        List<Coord> coords = new ArrayList<Coord>();{


            // for each line in the file
            while(sc.hasNextLine()) {
                String[] numstrs = sc.nextLine().split("\\s+"); 

                Coord c = new Coord();


                c.a = Integer.parseInt(numstrs[1]);
                c.b = Integer.parseInt(numstrs[2]);
                c.c = Integer.parseInt(numstrs[3]);
                c.d = Integer.parseInt(numstrs[4]);
                c.e = Integer.parseInt(numstrs[5]);
                c.f = Integer.parseInt(numstrs[6]);

                coords.add(c);

            }
// now you have all coords in memory
            {
for(int i=0; i<coords.size(); i++ ) 
    for( int j=0; j<coords.size(); j++) 
    {
        Coord c1 = coords.get(i);
        Coord c2 = coords.get(j);
        double foo = ((c1.a - c2.a) * (c1.a - c2.a)) *1 ;
        double goo = ((c1.b - c2.b) * (c1.b - c2.b)) *1 ;
        double hoo = ((c1.c - c2.c) * (c1.c - c2.c)) *2 ;
        double joo = ((c1.d - c2.d) * (c1.d - c2.d)) *2 ;
        double koo = ((c1.e - c2.e) * (c1.e - c2.e)) *4 ;
        double loo = ((c1.f - c2.f) * (c1.f - c2.f)) *4 ;
        double zoo = Math.sqrt(foo + goo + hoo + joo + koo + loo);

        DecimalFormat df = new DecimalFormat("#.###");
        pout.println(i + " " + j + " " + df.format(zoo));
        System.out.println(i);

    }
    pout.flush();
    pout.close();
            }
        }
    }   
}

Я ценю любую помощь, которую может предложить каждый.

Ответы [ 2 ]

3 голосов
/ 20 апреля 2011

Разделение внутреннего цикла for на отдельные задачи выглядит хорошим кандидатом на то, где сделать этот процесс многопоточным. Вот один из способов сделать это с помощью ExecutorService и Futures

    final ExecutorService executor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
    final List<Future<String>> results = new LinkedList<Future<String>>();
    // now you have all coords in memory
    for (int i = 0; i < coords.size(); i++) {
        final int index = i;
        final Coord c1 = coords.get(index);
        results.add(executor.submit(new Callable<String>() {
            public String call() {
                final StringBuilder stringBuilder = new StringBuilder();
                for (int j = 0; j < coords.size(); j++) {
                    final Coord c2 = coords.get(j);
                    final double foo = ((c1.a - c2.a) * (c1.a - c2.a)) * 1;
                    final double goo = ((c1.b - c2.b) * (c1.b - c2.b)) * 1;
                    final double hoo = ((c1.c - c2.c) * (c1.c - c2.c)) * 2;
                    final double joo = ((c1.d - c2.d) * (c1.d - c2.d)) * 2;
                    final double koo = ((c1.e - c2.e) * (c1.e - c2.e)) * 4;
                    final double loo = ((c1.f - c2.f) * (c1.f - c2.f)) * 4;
                    final double zoo = Math.sqrt(foo + goo + hoo + joo + koo + loo);

                    final DecimalFormat df = new DecimalFormat("#.###");
                    stringBuilder.append(index + " " + j + " " + df.format(zoo));
                    System.out.println(index);
                }
                return stringBuilder.toString();
            }
        }));
    }
    for (Future<String> result : results) {
        pout.print(result.get());
    }
    pout.flush();
    pout.close();
    executor.shutdown();

Для кластеризации, я думаю, Hazelcast предлагает хорошее решение, которое позволит вам определить общий ExecutorService и общие коллекции. Вам потребуются два вида узлов: один узел, отвечающий за все операции ввода-вывода и создающий список координат, а также отправляющий задачи. И узел обработки, который просто выполняет задачи. Это все мое мнение о том, как я могу это сделать. Однако, если ваш набор данных достаточно мал, чтобы поместиться в памяти, вероятно, не стоит усилий, чтобы разделить обработку так много.

1 голос
/ 20 апреля 2011

Это выглядит очень распараллеливаемым для меня. Почему у вас нет потоков, обрабатывающих одну строку данных за раз? Вы можете использовать AtomicInteger для подсчета количества строк, заявленных рабочими потоками. Каждый поток должен выполнить counter.getAndIncrement, чтобы заставить строку работать (если он возвращает coords.size() или выше, поток должен завершиться), затем выполнить всю математику для этой строки и повторить.

Печать будет не в порядке, но вы можете вместо этого заполнить некоторые буферы результатами, а затем быстро напечатать все в конце.

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