Друзья, которые использовали параллельные пакеты Java, могут быть знакомы с будущим (интерфейс). Будущее даже напрямую поддерживается на уровне синтаксиса на некоторых языках домена (таких как Alice ML).
Здесь мы возьмем java.util.concurrent.future в качестве примера, чтобы кратко рассказать о конкретном методе работы будущего. Сам объект будущего может рассматриваться как явная ссылка, ссылка на результаты асинхронной обработки. Благодаря своему асинхронному характеру объект, который он ссылается, может быть недоступен в начале творения (например, он все еще работает, сетевая передача или ожидание). В настоящее время, если поток программы, которая получает будущее, не спешит использовать объект, на который ссылаются будущее, то она может сделать все, что вы хотите. быть двумя ситуациями:
Я надеюсь увидеть этот объект доступным и завершить некоторые связанные с ним процессы последующих процессов. Если это действительно недоступно, вы также можете ввести другие филиалы.
«Без вас моя жизнь потеряет свое значение, поэтому даже если море исчезнет, я буду ждать вас». -время)
Для первого случая вы можете определить, готов ли ссылочный объект, позвонив в Future.isdone () и принять различную обработку;
Получить (длительный тайм -аут, время UNIT) ожидает, пока объект будет готов путем синхронной блокировки. Независимо от того, блокируется или возвращено фактическое время выполнения, зависит от времени вызовов get () и порядок готовности объекта.
Проще говоря, будущий режим может соответствовать потребностям параллелизма, управляемых данными, в непрерывных процессах, не только получая улучшение производительности в одновременном выполнении, но и простоту и элегантность непрерывных процессов.
Сравнение с другими параллельными дизайнами дизайна
В дополнение к будущему, другие общие шаблоны конструкции параллелизма включают в себя «управление обратным вызовом (в многопоточной среде)», «Сообщение/событие (в модели актера)» и т. Д.
Обратный вызов является наиболее распространенным асинхронным режимом параллелизма, который имеет высокую непосредственную и простую конструкцию интерфейса. Но по сравнению с будущим, его недостатки также очень очевидны. Во -первых, обратные вызовы в многопоточных средах обычно выполняются в потоке модуля, которые запускают обратный вызов, что означает, что потоки взаимных вопросов необходимо учитывать при написании методов обратного вызова; Выполнить обратные вызовы для пользовательских приложений, которые также являются относительно небезопасными, потому что вы не можете определить, сколько времени это займет или какие исключения это произойдут, что может косвенно повлиять на непосредственность и надежность этого модуля; Последовательность. Следовательно, интерфейс обратного вызовов подходит для сценариев, в которых необходимо выполнить только простые задачи в обратном вызове и не должны объединяться с другими процессами.
Недостатки вышеупомянутых режимов обратного вызова - это именно сильные стороны будущего. Поскольку использование будущего состоит в том, чтобы естественным образом включить асинхронные драйверы данных в последовательные процессы, вам вообще не нужно рассматривать проблемы с нитью. быть упомянутым ниже «Ленивое будущее»). С другой стороны, модули, которые обеспечивают будущие интерфейсы, не должны беспокоиться о проблемах надежности, таких как интерфейсы обратного вызова и их потенциальное непосредственное влияние на этот модуль.
Другим распространенным параллельным шаблоном проектирования является «Сообщение (событие), управляемое», которое обычно используется в модели актера: запрашивающая служба отправляет сообщение поставщику услуг, а затем продолжает выполнять последующие задачи, которые не полагаются на результаты обработки услуг. и зависит от этого, если вам нужно полагаться на него. Хотя этот параллельный управление на основе машины на основе состояния является более подходящим для последовательных процессов непрерывности, чем обратные вызовы, разработчики должны сократить непрерывный процесс в несколько специфических для состояния подпроцессов в соответствии с призывом асинхронного обслуживания, что искусственно увеличивает сложность развития. Использование будущего режима может избежать этой проблемы и не нужно разбивать непрерывные процессы для асинхронных вызовов. Однако следует отметить одну вещь: метод Future.get () может блокировать выполнение потока, поэтому он обычно не может быть напрямую включать в обычную модель актера. (Модель актера на основе Coroutine может лучше разрешить этот конфликт)
Гибкость будущего также отражается в его свободном выборе между синхронизацией и асинхронным выбором разработчиков может свободно решить, нужно ли им ждать [Future.isdone ()], когда ждать [future.get ()] и как долго ждать в соответствии с потребности процесса. Например, вы можете решить, использовать ли этот пробел для выполнения других задач в зависимости от того, готовы ли данные, что довольно удобно для реализации механизма «асинхронного прогнозирования ветвей».
Производство будущего
В дополнение к основным формам, упомянутым выше, будущее также имеет богатые производные изменения, поэтому вот несколько распространенных.
Ленивое будущее
В отличие от общего будущего, Lazy Future не начинает активно готовить ссылочный объект в начале создания, но ожидает, пока объект не будет запрашивается до начала соответствующей работы. Следовательно, само по себе ленивое будущее не предназначено для достижения параллелизма, но в качестве отправной точки требует сохранения ненужных вычислительных ресурсов, а его эффект аналогичен лямбда/закрытию. Например, при разработке определенных API вам может потребоваться вернуть набор информации, и расчет некоторых из них может потреблять значительные ресурсы. Тем не менее, абонент может не быть обеспокоен всей этой информацией, поэтому предоставление объектов, которые требуют большего количества ресурсов в форме ленивого будущего, может сохранять ресурсы, когда вызывающему абоненту не нужно использовать конкретную информацию.
Кроме того, Lazy Future также может быть использовано, чтобы избежать ненужных взаимных исключений, вызванных преждевременным приобретением или блокировкой ресурсов.
Обещать
Обещание может рассматриваться как специальная ветвь будущего. Но обещание используется для явного представления сценариев, в которых асинхронные процессы не запускаются напрямую вызывающим абонентом. Например, управление временем будущего интерфейса, его асинхронный процесс не запускается не вызывающим абонентом, а системными часами. подписчик, но подписчиком. Следовательно, по сравнению со стандартным будущим, интерфейс перспектива обычно имеет дополнительный набор () или Fulfill () интерфейс.
Многоразовое будущее
Регулярное будущее-это одноразовое, что означает, что когда вы получаете асинхронные результаты обработки, сам будущий объект теряет свое значение. Но специально разработанное будущее также может быть использовано повторно, что очень полезно для данных, которые можно изменить несколько раз. Например, интерфейс в стиле будущего, предоставленный распределенной системой подписки Taobao, позволяет использовать несколько вызовов WaitNext () (эквивалентно Future.get ()). Последний звонок. Преимущество этой конструкции заключается в том, что пользователь интерфейса может реагировать на изменения в данных подписки в любое подходящее время или просто через бесконечный цикл в независимой потоке, а также учитывая другие задачи по времени или даже ожидание нескольких задач в то же время. Упрощенные примеры следующие:
for (;;) {gayNextSchedTaskTime (;;); .}} doscheduledTask ();} Использование будущего
Во -первых, давайте перечислим кусок кода в Java.
//: conturance/callabledemo.javaimport java.util.concurrent.*; импортировать java.util.*; String call () {return "Результат TaskWithResult" + id; new ArrayList <Future <String >> (); пытаться : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : ::::::::::::::::: :::::::::::::::::: :::::: ::::::::: {// get () блокирует до завершения: system.out.println (fs.get ()) ; :result of TaskWithResult 0result of TaskWithResult 1result of TaskWithResult 2res ult of TaskWithResult 3result of TaskWithResult 4result of TaskWithResult 5result of TaskWithResult 6result of TaskWithResult 7result of TaskWithResult 8result of TaskWithResult 9*///:~Чтобы объяснить использование будущего, во -первых, метод exec exec exec exectorsers exec для создания будущего объекта, который использует конкретный тип результата обратного возврата для параметризации. Вы можете использовать метод isdone (), чтобы запросить, было ли будущее завершено. Когда задача будет выполнена, она имеет результат, и вы можете вызвать метод get (), чтобы получить результат. Вы также можете вызвать get () непосредственно без проверки Isdone (). Вы можете вызвать функцию get () с тайм -аутом или сначала вызовать (), чтобы увидеть, выполнена ли задача, а затем вызовите get ().