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

Мой код ниже:

  Executer myRunnable = new Executer();
    Thread t = new Thread(myRunnable);
    t.start();
    t.join();
    int tdist=(Executer.returnPathValue());
    int []comparet = returnSearchedPath();

    Thread t1 = new Thread(myRunnable);
    t1.start();
    t1.join();

    int t1dist=(Executer.returnPathValue());
    int []comparet2 = returnSearchedPath();

    if(tdist<t1dist){
        printPath(comparet);
        System.out.println(tdist);
    }
    else{
        printPath(comparet2);
        System.out.println(t1dist);
    }

Результатом этого будет

SEARCH COMMENCING:
32 10 51 13 12 26 24 23 47 45 15 49 19 29 28 46 25 27 11 50 3 43 22 20 41 1 6 16 2 17 30 21 0 48 31 44 18 40 7 8 9 14 5 4 37 36 33 34 35 38 39 42 32->dist 8904

Моя единственная проблема СЕЙЧАС - добиться того же результата без использования .join () и позволить потокам работать одновременно. Любые идеи?

0
rahul chawla 13 Мар 2018 в 23:39

2 ответа

Лучший ответ

Должен ли я ждать, пока они оба завершатся, в основном я хочу достичь того же результата, что и я, без использования .join

Я думаю, что понял. Есть методы, с помощью которых вы можете получить вывод из потока, не ожидая его специально. Базовая техника - модель производитель-потребитель.

https://en.wikipedia.org/wiki/Producer%E2%80%93consumer_problem

Вот простой способ сделать это на Java. Сначала создайте глобальную потокобезопасную очередь.

public class Global {

  public static final ConcurrentLinkedQueue outputQueue = new ConcurrentLinkedQueue();

}

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

public class MyTask implements Runnable {

  private final Queue output;

  /** 'q' must be thread safe */
  public MyTask( Queue q ) {
    output = q;
  }

  @Override
  public void run() {

    // do stuff

    int [] path = ...
    output.add( path );
  }

}

Теперь вы можете просто прочитать очередь, чтобы получить результат, или решить не читать ее. Вы также можете выделить один поток для вывода и позволить основному потоку делать другие вещи. (Это то, что обычно делается в проблеме производитель-потребитель.) Вы также можете произвести вывод, но не закончить, и продолжать производить результаты и добавлять их в очередь, когда вы можете их вычислить. Это хорошо работает для задач прогрессивного типа.

Этот код не был протестирован, и извините за использование необработанных типов, это всего лишь быстрый пример.

0
markspace 14 Мар 2018 в 00:25

По сути, вам нужен ArrayList ваших потоков и переменная для хранения текущего наилучшего пути. В классе потока вам понадобятся два синхронизированных метода. Синхронизированные методы являются поточно-ориентированными. Это означает, что если у вас работает несколько потоков, вы можете безопасно изменять данные в другом потоке. Если вы хотите узнать больше о том, как это работает, перейдите по этой ссылке здесь. Вам понадобится один метод для обновления текущего лучшего маршрута, если маршрут, найденный потоком, меньше, чем текущий лучший, и вам понадобится одна функция, чтобы удалить себя из ArrayList в основном потоке, когда он будет завершен. Это означает, что у вас будет блокирующий цикл while в основном потоке, который выглядит примерно так:

//Where threads is the ArrayList of all of your threads
while(!threads.isempty()){
    //Wait here
}

Затем, после этого, вы можете проверить текущую лучшую переменную пути, и она должна быть лучшей. Теперь вам не нужно ждать, пока он выйдет из цикла while, чтобы обновить JFrame. Вы можете изменить JFrame, когда текущее лучшее не соответствует тому, что текущий JFrame показывает внутри цикла while, но как только вы выйдете из него, вы должны дважды проверить, отображается ли правильный. Выход означает, что все потоки выполнены, поэтому окончательным ответом будет все, что осталось в текущем лучшем пути.

0
Dax Loy 13 Мар 2018 в 21:22