Книга: Программирование на языке Ruby

13.2.10. Параллельное рекурсивное удаление

13.2.10. Параллельное рекурсивное удаление

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

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

Отметим также, что в блок потока передается полное имя файла fullname, чтобы не нужно было беспокоиться по поводу того, что поток обращается к переменной, которую кто-то еще изменяет. Поток делает для себя локальную копию fn этой переменной.

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

def delete_all(dir)
 threads = []
 Dir.foreach(dir) do |e|
  next if [".",".."].include? e # Пропустить . и ..
  fullname = dir + "/" + e
  if FileTest.directory?(fullname)
   threads << Thread.new(fullname) {|fn| delete_all(fn) }
  else
   File.delete(fullname)
  end
 end
 threads.each { |t| t.join }
 Dir.delete(dir)
end
delete_all("/tmp/stuff")

Будет ли работать такая программа быстрее, чем ее вариант без потоков? В наших тестах получалось по-разному. Возможно, это зависит от операционной системы и структуры конкретного каталога — глубины, количества файлов и т.д.

Оглавление книги


Генерация: 1.234. Запросов К БД/Cache: 3 / 1
поделиться
Вверх Вниз