Разъяснение по поводу потоков и выполненных циклов в какао

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

1) performSelectorOnMainThread

Вышеупомянутое просто регистрирует событие в основном цикле выполнения, или это - так или иначе новый поток даже при том, что в методе говорится "mainThread"? Если цель потоков состоит в том, чтобы уменьшить обработку на основном потоке, как это помогает?

2) RunLoops

Действительно ли это верно, что, если я хочу создать абсолютно отдельный поток, я использую "detachNewThreadSelector"? Вызов запускается на этом новичке, значение по умолчанию выполняет цикл для потока, который был создан? Раз так, где выполненные циклы входят в него?

3) И Наконец, я видел, что примеры используют NSOperationQueue. Действительно ли это верно, чтобы сказать, что при использовании performSelectorOnMainThread, потоки находятся в очереди так или иначе, таким образом, NSOperation не нужен?

4) Я должен забыть обо всем этом и просто использовать Центральную Отправку вместо этого?

10
задан dubbeat 7 May 2010 в 14:38
поделиться

2 ответа

Циклы выполнения

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

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

[NSRunLoop currentRunLoop]

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

PerformSelector

performSelectorOnMainThread: добавляет цель и селектор к специальному входному источнику, называемому performSelector входному источнику .Цикл выполнения основного потока выводит из очереди этот входной источник и обрабатывает вызов метода один за другим как часть своего цикла обработки событий.

NSOperation / NSOperationQueue

Я думаю о NSOperation как о способе явного объявления различных задач внутри приложения, что занимает некоторое время, но может выполняться в основном независимо. Это проще в использовании, чем самостоятельно отсоединять новую ветку и поддерживать различные вещи самостоятельно. Основной NSOperationQueue автоматически поддерживает набор фоновых потоков, которые он повторно использует, и запускает NSOperations параллельно. Так что да, если вам просто нужно поставить в очередь операции в основной поток, вы можете отказаться от NSOperationQueue и просто использовать performSelectorOnMainThread: , но это не главное в NSOperation .

GCD

GCD - это новая инфраструктура, представленная в Snow Leopard. NSOperationQueue теперь реализован поверх него. Он работает на уровне функций / блоков. Подача блоков в dispatch_async чрезвычайно удобна, но для более крупного фрагмента операций я предпочитаю использовать NSOperation , особенно когда этот фрагмент используется из разных мест в приложении.

Резюме

Вам необходимо прочитать Официальный документ Apple ! На этот счет есть много информативных сообщений в блогах.

26
ответ дан 3 December 2019 в 14:33
поделиться

1)performSelectorOnMainThread

Разве вышеописанное просто регистрирует событие в основном цикле выполнения...

Вы спрашиваете о деталях реализации. Не беспокойтесь о том, как это работает.

Что это делает, так это выполняет селектор в основном потоке.

... или это каким-то образом новый поток, хотя метод говорит "mainThread"?

Нет.

Если цель потоков - разгрузить обработку на основном потоке, как это поможет?

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

Существуют и другие методы для выполнения действий в новых вторичных потоках, хотя NSOperationQueue и GCD обычно являются более простыми способами.

2) RunLoops

Правда ли, что если я хочу создать полностью отдельный поток, я использую "detachNewThreadSelector"?

Это не имеет никакого отношения к циклам выполнения.

Да, это один из способов начать новый поток.

Вызывает ли вызов start при этом цикл выполнения по умолчанию для созданного потока?

Нет.

Я не знаю, что вы здесь "вызываете start". detachNewThreadSelector: ничего не возвращает, а сразу запускает поток. Я думаю, вы перепутали это с NSOperations (который вы также не запускаете сами - это работа очереди).

Если так, то где здесь циклы выполнения?

Циклы выполнения просто существуют, по одному на поток. Со стороны реализации они, вероятно, лениво создаются по требованию.

3) И наконец, я видел примеры с использованием NSOperationQueue. Верно ли утверждение, что при использовании performSelectorOnMainThread потоки все равно попадают в очередь, поэтому NSOperation не нужен?

Эти две вещи не связаны.

performSelectorOnMainThread: делает именно это: Выполняет селектор на основном потоке.

Операции NSO выполняются во вторичных потоках, по одной на операцию.

Очередь операций определяет порядок, в котором запускаются операции (и их потоки).

Сами потоки не ставятся в очередь (за исключением, возможно, планировщика, но это часть ядра, а не вашего приложения). Операции ставятся в очередь, и они запускаются в таком порядке. После запуска их потоки выполняются параллельно.

4) Должен ли я забыть обо всем этом и просто использовать Grand Central Dispatch вместо этого?

GCD - это более или менее тот же набор понятий, что и очереди операций. Вы не поймете одну из них до тех пор, пока не поймете другую.


Так для чего же все эти вещи нужны?

Циклы выполнения

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

Обычно вы не обрабатываете цикл выполнения самостоятельно при создании запланированного таймера; таймер добавляет себя в цикл выполнения за вас.

Потоки

Потоки позволяют нескольким вещам происходить в одно и то же время на разных процессорах. Вещь 1 может происходить в потоке A (на процессоре 1), в то время как вещь 2 происходит в потоке B (на процессоре 0).

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

NSOperationQueue и GCD

У вас есть вещь, которую вам нужно сделать. Это операция. Вы не можете выполнить ее в основном потоке, иначе вы бы просто отправили сообщение, как обычно; вам нужно выполнить ее в фоновом режиме, во вторичном потоке.

Чтобы добиться этого, выразите ее либо как объект NSOperation (вы создаете подкласс NSOperation и инстанцируете его) или блок (или оба), затем добавляете его либо в NSOperationQueue (NSOperations, включая NSBlockOperation), либо в очередь диспетчеризации (голый блок).

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

Так что же мне делать?

Я бы не рекомендовал создавать потоки напрямую. Вместо этого используйте NSOperationQueue или GCD; они заставляют вас лучше мыслить, что снизит риск того, что ваш потоковый код вызовет головную боль.

Для вещей, которые выполняются периодически, не вписываясь в модель "вещь, которую мне нужно сделать" блоков NSOperations и GCD, подумайте о том, чтобы просто использовать цикл выполнения в основном потоке. Есть шанс, что вам не нужно помещать его в поток. Например, цикл рендеринга в 3D-игре может представлять собой простой таймер.

7
ответ дан 3 December 2019 в 14:33
поделиться
Другие вопросы по тегам:

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