Распараллеливание методов в Rails

Вы также можете попробовать следующее:

JFileChooser c= new JFileChooser();
c.showOpenDialog(c);
File write_file = c.getSelectedFile();
String Content = "Writing into file"; //what u would like to append to the file



try 
{
    RandomAccessFile raf = new RandomAccessFile(write_file, "rw");
    long length = raf.length();
    //System.out.println(length);
    raf.setLength(length + 1); //+ (integer value) for spacing
    raf.seek(raf.length());
    raf.writeBytes(Content);
    raf.close();
} 
catch (Exception e) {
    //any exception handling method of ur choice
}
17
задан AdamNYC 21 May 2013 в 03:24
поделиться

4 ответа

У Ruby есть превосходный камень обещания . Ваш пример будет выглядеть так:

require 'future'

def method_one
...
def method_nth

def summary
  result1 = future { method_one }
  ......
  resultn = future { method_nth }
  collect_results result1, ..., resultn
end

Просто, не правда ли? Но давайте перейдем к более подробной информации. Это объект будущего:

result1 = future { method_one }

Это означает, что result1 оценивается в фоновом режиме. Вы можете передать его другим методам. Но result1 пока не дал никакого результата, он все еще обрабатывается в фоновом режиме. Подумайте о том, чтобы обойти Нить. Но главное отличие в том, что в тот момент, когда вы пытаетесь прочитать его, вместо того, чтобы передавать его, он блокирует и ждет результата в этой точке. Таким образом, в приведенном выше примере все переменные result1 .. resultn будут обрабатываться в фоновом режиме, но когда придет время собирать результаты и когда вы попытаетесь фактически прочитать эти значения, чтение будет ожидать завершения запросов на этот момент.

Установите драгоценный камень promise и попробуйте следующее в консоли Ruby:

require 'future'
x = future { sleep 20; puts 'x calculated'; 10 }; nil
# adding a nil to the end so that x is not immediately tried to print in the console
y = future { sleep 25; puts 'y calculated'; 20 }; nil

# At this point, you'll still be using the console!
# The sleeps are happening in the background

# Now do:
x + y
# At this point, the program actually waits for the x & y future blocks to complete

Редактировать: опечатка в result, должна была быть result1, изменить echo на puts

23
ответ дан Paulo Fidalgo 21 May 2013 в 03:24
поделиться

Вы можете взглянуть на новую опцию в городе: Камень футороскопа . Как вы можете видеть из анонса блога , он пытается решить ту же проблему, с которой вы сталкиваетесь, выполняя одновременные запросы API. Кажется, у него довольно хорошая поддержка и хорошее тестовое покрытие.

4
ответ дан Sebastian Palma 21 May 2013 в 03:24
поделиться

Предполагая, что ваша проблема - медленный внешний API, решением может быть использование либо многопоточного, либо асинхронного программирования. По умолчанию при выполнении ввода-вывода ваш код будет заблокирован. По сути, это означает, что если у вас есть метод, который выполняет HTTP-запрос для извлечения некоторого JSON, ваш метод сообщит вашей операционной системе, что вы собираетесь спать, и вы не хотите, чтобы его разбудили, пока операционная система не получит ответ на этот запрос. Поскольку это может занять несколько секунд, вашему приложению просто придется ждать.

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

Итак, вопрос в вашем случае: нужно ли нам ждать завершения одного метода, прежде чем мы сможем вызвать другой? В случае, если поведение method_two зависит от результата method_one, тогда да. Но в вашем случае кажется, что это отдельные единицы работы без взаимозависимости. Таким образом, существует потенциал для выполнения параллелизма.

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

def main_method
  Thread.new { method_one }
  Thread.new { method_two }
  Thread.new { method_three }
end

def method_one
  # something_slow_that_does_an_http_request
end

def method_two
  # something_slow_that_does_an_http_request
end

def method_three
  # something_slow_that_does_an_http_request
end

Вызов main_method вызовет выполнение всех трех методов в том, что кажется параллельным. В действительности они все еще обрабатываются последовательно, но вместо того, чтобы переходить в спящий режим, когда блоки method_one блокируются, Ruby просто вернется в основной поток и переключится обратно в поток method_one, когда ОС подготовит входные данные.

Если предположить, что на выполнение каждого метода уходит две 2 мс минус ожидание ответа, это означает, что все три метода запускаются через 6 мс - практически мгновенно.

Если мы предположим, что для ответа требуется 500 мс, это означает, что вы можете сократить общее время выполнения с 2 + 500 + 2 + 500 + 2 + 500 до всего 2 + 2 + 2 + 500 - другими словами от 1506 мс до 506 мс.

Будет казаться, что методы работают одновременно, но на самом деле они просто спят одновременно.

В вашем случае, однако, у вас есть проблема, потому что у вас есть операция, которая зависит от завершения набора предыдущих операций. Другими словами, если у вас есть задачи A, B, C, D, E и F, то A, B, C, D и E могут выполняться одновременно, но F не может выполняться до A, B, C, D и E. все завершены.

1117 Существуют разные способы решения этой проблемы. Давайте посмотрим на простое решение, которое создает сонный цикл в главном потоке, который периодически проверяет список возвращаемых значений, чтобы убедиться, что какое-то условие выполнено.

def task_1
# Something slow
return results
end

def task_2
# Something slow
return results
end

def task_3
# Something slow
return results
end

my_responses = {}
Thread.new { my_responses[:result_1] = task_1 }
Thread.new { my_responses[:result_2] = task_2 }
Thread.new { my_responses[:result_3] = task_3 }

while (my_responses.count < 3) # Prevents the main thread from continuing until the three spawned threads are done and have dumped their results in the hash.
  sleep(0.1) # This will cause the main thread to sleep for 100 ms between each check. Without it, you will end up checking the response count thousands of times pr. second which is most likely unnecessary.
end

# Any code at this line will not execute until all three results are collected.

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

Если вы хотите заняться многопоточным программированием, я рекомендую эту книгу: http://www.amazon.com/Java-Concurrency-Practice-Brian-Goetz/dp/0321349601

Он сосредоточен вокруг Явы, но объясненные ловушки и концепции универсальны.

3
ответ дан Niels B. 21 May 2013 в 03:24
поделиться

Вы должны проверить Sidekiq .

RailsCasts эпизод о Sidekiq.

0
ответ дан frido 21 May 2013 в 03:24
поделиться
Другие вопросы по тегам:

Похожие вопросы: