Понимание параллели существует и найти - PullRequest
9 голосов
/ 12 декабря 2011

Я беру List[Int] и хочу найти значение x, где x * 10 > 500 параллельно. Так что exists должно возвращать true, если список содержит любое значение 51 или больше.

def f(x: Int) = {
  println("calculating for " + x)
  Thread.sleep(100 - x)
  println("finished " + x)
  x * 10
}

val res = List.range(1, 100).par.exists(f(_) > 500)

Что дает результаты:

calculating for 1
calculating for 25
calculating for 50
calculating for 75
calculating for 13
finished 75          // <-- first valid result found: 75 * 10 > 500
finished 50
calculating for 51   // but it kicks off more expensive calculations
finished 25
calculating for 26   
finished 13
calculating for 14   
finished 1
calculating for 2
finished 51
finished 26
calculating for 27   // and more
finished 14
calculating for 15
finished 2
calculating for 3
finished 27
calculating for 28
finished 15
calculating for 16
finished 3
calculating for 4    // and more...
finished 28
calculating for 29
finished 16
calculating for 17
finished 29
calculating for 30
finished 4
calculating for 5
finished 17
calculating for 18
finished 30
finished 5
calculating for 6
finished 18
finished 6
res: Boolean = true

Я использую двухъядерный компьютер с Scala 2.9.1.

Что здесь происходит? Это работает как задумано? Почему бы просто не отправить сообщение другим потокам, чтобы прервать миссию, как только будет найден первый результат? Это может быть довольно дорого, если f является дорогостоящим вычислением.

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

Ответы [ 2 ]

2 голосов
/ 12 декабря 2011

Почему бы просто не отправить сообщение другим потокам, чтобы прервать миссию, как только будет найден первый результат?

Потому что это невозможно.JAVA НЕ ПОЗВОЛЯЕТ ВАМ ЭТО.Или, скорее, это так, но это устарело.

См. Описание (устарело) Thread.stop():

Этот метод по своей сути небезопасен.Остановка потока с помощью Thread.stop приводит к тому, что он разблокирует все заблокированные мониторы (как естественное следствие непроверенного исключения ThreadDeath, распространяющегося вверх по стеку).Если какой-либо из объектов, ранее защищенных этими мониторами, находился в несогласованном состоянии, поврежденные объекты становятся видимыми для других потоков, что может привести к произвольному поведению.Многие варианты использования stop должны быть заменены кодом, который просто изменяет некоторую переменную, чтобы указать, что целевой поток должен прекратить работу.Целевой поток должен регулярно проверять эту переменную и упорядоченно возвращаться из своего метода run, если переменная указывает, что она должна прекратить работу.Если целевой поток ожидает длительные периоды (например, для переменной условия), для прерывания ожидания следует использовать метод прерывания.Для получения дополнительной информации см. . Почему Thread.stop, Thread.suspend и Thread.resume устарели? .

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

1 голос
/ 12 декабря 2011

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

В выражениях быстрого вызова следующий вызов не запускается, если результат найден - это легко.

Но как вы бежите за заданием, выполненным вручную, и перехватываете его снова, чтобы остановитьЭто?Вам необходимо знать, кто из них уже закончил, и может вступить в состояние гонки, потому что во время тестирования, если он все еще работает, он может вернуть «истина», но потом закончить немедленно.

Функция, которая вызывается из exists, может сама запускать новые потоки - как их вообще следует останавливать извне?Предоставляя необязательный stop execution -метод в качестве второго параметра, возможно?

...