Страницы

Поиск по вопросам

пятница, 20 декабря 2019 г.

Как распараллелить циклы?

#потоки_данных #java #циклы


Помогите разобраться с тем, как можно распараллеливать циклы..   
Вот допустим у меня есть некоторый метод, который должен вызываться с разными входными
параметрами в цикле. Результат записывается в массив.    
Каждая итерация цикла независима от других. Как распараллелить этот процесс?  

И еще, как мне быть в такой ситуации: 

 public class MainClass(){

  public void main(){

    Generator g = new Generator();

    for (int i = 0; i < 10; i++){
      ArrayList res = g.funcion(i); // здесь все должно выполняться последовательно
      System.put.println(res.size());
    }
  }   
}   
public class Generator(){

  public function(int i){

    // Вот тут то и хотелось бы распараллелить выполнение метода function2
    ArrayList res = new ArrayList();
    res.addAll(function2(i));
    res.addAll(function2(i*i));

  }

  public function2(int i){
    // ...
  }
}
    


Ответы

Ответ 1



Если каждая итерация цикла из main не зависит от других, то логичнее было бы запускать каждую итерацию в отдельном потоке (а не вызовы function2, как вы хотите). Тогда вам понадобится список результатов работы каждого потока и какой-нибудь пул потоков, отслеживающий, завершили ли они работу. После запуска всех потоков, основной поток будет засыпать, а когда все потоки отработают, пул его разбудит, он пройдётся по результатам, и выведет их на экран. Для хранения результатов работы потоков лучше использовать не простой List, а потокобезопасный. Такой можно получить либо при помощи Collections.synchronizedList(List list), либо при помощи ReentrantLock, либо заворачивая обращения к этому списку в synchronized-блок. В качестве пула потоков можно использовать ThreadPoolExecutor. В этой статье кратко описано, как им пользоваться. А ещё можно дождаться выхода Java 8, в которой всё это реализовано на уровне API.

Ответ 2



Есть нечто вроде LinQ для Java - библиотека LambdaJ с помощью ее можно обращаться с коллекциями как некими сущностями не прибегая к циклу по их внутренностям. Не уверен, что на выходе будет параллельное выполнение - это уже зависит от компилятора. Но синтаксически будет довольно красиво как в SQL. Реальное распараллеливание можно сделать с помощью Thread'ов, но результат вам не понравится...

Ответ 3



Создай класс, который будет реализовать интерфейс Runnable public class YourClass implements Runnable{ private int myInt; public YourClass(int _myInt){ myInt = _myInt; } @Override public void run(){ // Твой код } } А вместо res.addAll(function2(i*i)); Напиши Thread thread = new Thread(new YourClass(i)); thread.start(); Код из function2 перенеси в run()

Ответ 4



как-то так: public abstract class ThreadHelper { public static void exec(Callable ...callable) throws InterruptedException { // validate input if (null == callable || 0 == callable.length) { return; } List> tasks = Arrays.asList(callable); // special for @IronVbif int cores = Runtime.getRuntime().availableProcessors(); // execute thread group ExecutorService threadpool = Executors.newFixedThreadPool(cores*2); threadpool.invokeAll(tasks); threadpool.shutdown(); } @SuppressWarnings("unchecked") public static void main(String[] args) { final List result = new LinkedList(); // callable one Callable callable = new Callable() { @Override public Object call() throws Exception { for (int i = 33; i < 77; i++) { result.add(i); Thread.sleep(15); } return null; } }; Callable callable2 = new Callable() { @Override public Object call() throws Exception { for (int i = 97; i < 133; i++) { result.add(String.valueOf((char)i)); Thread.sleep(25); } return null; } }; try { exec(callable, callable2); } catch (InterruptedException e) { System.out.println("failed: " + e.getLocalizedMessage()); } System.out.println(result); } } google: java parallel execution

Комментариев нет:

Отправить комментарий