проблема параллелизма Java - PullRequest
0 голосов
/ 31 июля 2011

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

public class MyRunnable implements Runnable {

private int startIndex;
private int endIndex;
private float[] tab;

public MyRunnable(int startIndex, int endIndex, float[] tab)
{
    this.startIndex = startIndex;
    this.endIndex = endIndex;
    this.tab = tab;
}

@Override
public void run() 
{
    System.out.println(Thread.currentThread());
    for(int i = startIndex; i < endIndex; i++)
    {
        tab[i] = i * 2;
    }

    System.out.println("Finished");
}

}

public class Test {

public static void main(String[] args) {

    int size = 10;
    int n_threads = 2;
    float tab[] = new float[size];

    for(int i = 0; i < size; i++)
    {
        tab[i] = i;
    }

    System.out.println(Thread.currentThread());

    for(int i = 0; i < size; i++)
    {
        System.out.println(tab[i]);
    }

    Runnable r1 = new MyRunnable(0, size / n_threads, tab );
    Runnable r2 = new MyRunnable(size / n_threads, size, tab );

    Thread t1 = new Thread(r1);
    Thread t2 = new Thread(r2);

    t1.start();
    t2.start();

    for(int i = 0; i < size; i++)
    {
        System.out.println(tab[i]);
    }

}

Ответы [ 3 ]

2 голосов
/ 31 июля 2011

Похоже, вы не ждете окончания потоков. Используйте метод join и добавьте

t1.join();
t2.join();

непосредственно перед выходным контуром.

2 голосов
/ 31 июля 2011

Как отмечают другие, вы не ждете, пока ваши потоки завершат выполнение.Вы должны следовать советам @Howard и @JK, и это решит вашу основную проблему.Если вы решите сделать больше с потоками и параллельной обработкой, я бы настоятельно рекомендовал изучить пакеты java.util.concurrent - в них есть много полезных классов, которые значительно облегчат вашу жизнь.

Я позволил себе перекодировать ваш пример, используя Callable и ExecutorService.Посмотрите пример кода ниже:

public static void main(String[] args) {

    int size = 10;
    int n_threads = 2;
    float tab[] = new float[size];

    for (int i = 0; i < size; i++) {
        tab[i] = i;
    }

    System.out.println(Thread.currentThread());

    for (int i = 0; i < size; i++) {
        System.out.println(tab[i]);
    }

    // Determine batch size, based off of number of available
    // threads.
    int batchSize = (int) Math.ceil((double) size / n_threads);
    System.out.println("Size: " + size + " Num threads: " + n_threads
            + " Batch Size: " + batchSize);

    // Create list of tasks to run
    List<Callable<Object>> tasks = new ArrayList<Callable<Object>>(
            n_threads);

    for (int i = 0; i < n_threads; i++) {
        tasks.add(Executors.callable(new MyRunnable(i * batchSize,
                ((i + 1) * batchSize) - 1, tab)));
    }

    // Create an executor service to handle processing tasks
    ExecutorService execService = Executors.newFixedThreadPool(n_threads);

    try {
        execService.invokeAll(tasks);
    } catch (InterruptedException ie) {
        ie.printStackTrace();
} finally {
    execService.shutdown();
}

    for (int i = 0; i < size; i++) {
        System.out.println(tab[i]);
    }
}

И внес одно небольшое изменение в ваш класс MyRunnable, который пропускал обработку по последнему индексу:

@Override
public void run() {
    System.out.println(Thread.currentThread());
    for (int i = startIndex; i <= endIndex; i++) {
        tab[i] = i * 2;
    }

    System.out.println("Finished");
}

Отлично работает, вы можете протестироватьдля себя.Существует множество других классов в java.util.concurrent, которые могут выполнять аналогичные функции, не стесняйтесь исследовать.

Удачи!

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

Вы можете дождаться окончания выполнения потоков, вставив вызовы к Thread.join () :

t1.join();
t2.join();

после вызова функции x.start() для приостановки до завершения потоков. В противном случае вы не сможете узнать, закончили ли они выполнение или нет.

Вам также следует рассмотреть возможность синхронизации ваших tab[] обращений в отдельных потоках с мьютексом / семафором или аналогичным механизмом и не обязательно выполнять вычисления непосредственно для переданной ссылки на массив, поскольку это может ограничить количество параллелизма (если имеется).

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