Lançado pela Apple em 2009, o Grand Central Dispatch foi construído para gerenciar tarefas executadas simultaneamente, enfileirá-las para execução e programá-las para execução em processadores desocupados em segundo plano.

Distribuído sob a licença Apache, o GCD contém uma biblioteca de código aberto comumente referida como GCD ou libdispatch. Esta biblioteca executa operações de tarefas pesadas em segundo plano, mantendo o thread principal funcionando sem problemas e fornecendo tempos de resposta mais rápidos.

GCD funciona com tarefas como um bloco vazio ou função que não aceita argumentos.

Discutiremos como o GCD fornece multithreading e filas, além de explorar quais problemas o GCD resolve com suas técnicas e recursos.

Threads, multithreading e filas no Grand Central Dispatch

Para realmente entender o GCD, revisaremos threads, multithreading e filas.

Tópicos

Threads no GCD contêm o thread principal e o thread de fundo; todas as tarefas são executadas nesses threads. É importante manter o thread principal o mais livre possível para que nossa IU permaneça rápida e responsiva. Todas as tarefas pesadas realizadas devem ser colocadas em segundo plano.

Multithreading

Como a CPU executa uma tarefa por vez, podemos usar multithreading para fazer a CPU alternar entre as tarefas, permitindo que execute várias tarefas ao mesmo tempo.

O multithreading aumenta a capacidade de resposta e diminui o atraso ao realizar várias tarefas, garantindo que o thread principal não seja interrompido.

Fila

Uma fila se parece com uma linha de ônibus. Imagine pessoas em uma estação de ônibus esperando para entrar em um ônibus. O primeiro da linha, que representa a fila, entra no ônibus e sai da linha, que na programação é chamado primeiro a entrar, primeiro a sair.

No GCD, uma fila é um grupo de blocos de código ou funções em espera para ser executado em um thread.

Existem dois tipos de filas:

  1. Uma fila serial que executa tarefas da primeira à última, uma de cada vez
  2. Uma fila simultânea executa todas as tarefas simultaneamente; as tarefas terminam com base na operação que está sendo realizada

Em relação às threads, as filas concorrentes funcionam na thread de segundo plano, enquanto a thread principal é a fila serial. Um aplicativo usa a fila principal para executar tarefas em série e despacha as tarefas de trabalho pesado para as filas simultâneas. É aqui que entra o Grand Central Dispatch.

O que o Grand Central Dispatch resolve?

Sem a capacidade de realizar tarefas pesadas no thread de segundo plano, as tarefas seriam realizadas em série, reduzindo o desempenho.

Mas, ao criar filas e colocar blocos de código na fila, o GCD leva as tarefas longas e pesadas para o thread de segundo plano para execução. Os blocos de código na fila aguardando execução são mantidos em um encerramento.

Técnicas de GCD

As técnicas usadas pelo GCD fornecem suporte abrangente para a execução de código simultâneo.

Revisaremos algumas das técnicas de GCD que são úteis para desenvolvedores iOS, incluindo:

  • Como agendar e gerenciar tarefas com DispatchQueue
  • Tarefas de agrupamento e sincronização como uma única unidade com DispatchGroup

DispatchQueue

É aqui que o GCD cria tarefas empacotando-as em um bloco ou função e colocando-as em uma fila, seja em ordem de execução ou complexidade. Isso mantém nossas filas de tarefas em ordem e ajuda a executá-las em série ou simultaneamente.

Existem três tipos de DispatchQueue :

  • A fila principal é serial, é executada no thread principal e é usada para operações relacionadas à IU
  • Filas globais são filas simultâneas e executam tarefas em ordem de prioridade
  • Filas personalizadas são filas seriais e simultâneas personalizadas

Crie um DispatchQueue com o seguinte:

 let dispatchQueue=DispatchQueue (rótulo:"myqueue")

Podemos então fazer com que as tarefas sejam executadas de forma síncrona ou assíncrona adicionando o código abaixo:

 let dispatchQueue=DispatchQueue (rótulo:"myqueue") //O código é executado de forma síncrona
dispatchQueue.sync { imprimir ("Faça algo síncrono")
} //O código é executado de forma assíncrona
dispatchQueue.async { print ("Faça algo assíncrono")
}

Se quisermos executar nossas tarefas apenas de forma síncrona, adicionamos o seguinte:

 let dispatchQueue=DispatchQueue (rótulo:"myqueue") //A tarefa é síncrona
dispatchQueue.sync { //Definir intervalo de tempo Thread.sleep (forTimeInterval: 5) imprimir ("Faça algo síncrono")
} imprimir ("Faça algo") //Faça algo síncrono
//Faça alguma coisa

Observe que print ("Faça algo") deve aguardar a conclusão da primeira tarefa. Nesse caso, a primeira tarefa atrasa 5s, é executada e passa para o próximo código.

Se precisarmos que nossas tarefas sejam executadas de forma assíncrona, DispatchQueue ainda pode nos ajudar. Ao executar tarefas de forma assíncrona, eles concluem em seu próprio tempo, enquanto o thread principal ainda executa de forma síncrona:

 let dispatchQueue=DispatchQueue (rótulo:"myqueue") dispatchQueue.async { Thread.sleep (forTimeInterval: 1) print ("Faça algo assíncrono")
} imprimir ("Faça algo") //Faça alguma coisa
//Faça algo assíncrono

Como executamos dispatchQueue.async para "Do something assynchronous", "Do something" retorna primeiro.

DispatchGroup

O objetivo principal de um DispatchGroup é esperar pelos dados. Conforme as tarefas são concluídas, eles esperam que todo o grupo seja concluído antes de passar para a próxima operação. Portanto, quando temos grupos de tarefas simultâneas, um DispatchGroup nos notifica quando as tarefas são concluídas.

Quando criamos um DispatchGroup , podemos criar uma fila simultânea e serial personalizada com suas tarefas assíncronas vinculadas ao mesmo grupo.

Se quisermos ser notificados quando nossas tarefas em cada grupo forem concluídas, podemos usar o group.notify , que vem do DispatchGroup declarado anteriormente:

 let group=DispatchGroup () //fila simultânea
let queue=DispatchQueue (rótulo:"com.logrocket.concurrentqueue", atributos:.concurrent) //Vincule a fila ao grupo
queue.async (grupo: grupo) { Thread.sleep (forTimeInterval: 3) imprimir ("Minha primeira tarefa")
} //fila serial
let queue2=DispatchQueue (rótulo:"com.logrocket.serialqueue", atributos:.serial) //Vincule a fila ao grupo
queue2.async (group: group) {//Grupo vinculado imprimir ("Minha segunda tarefa")
} //Notifique-nos para a conclusão de tarefas no thread principal.
group.notify (queue: DispatchQueue.main) { Thread.sleep (forTimeInterval: 1) imprimir ("Todas as tarefas simultâneas realizadas")
} imprimir ("Aguardando tarefas") /* Resultado: Minha tarefa Tarefa simultânea realizada Esperando por tarefas
*/

Isso funciona de forma semelhante aos semáforos, mas, em nosso caso, se nossas tarefas não tocam um recurso compartilhado, devemos usar um DispatchGroup .

Conclusão

Com o GCD, podemos transferir a responsabilidade de gerenciar threads do aplicativo principal para o sistema operacional. Alcançar um padrão de execução simultânea não é mais algo pelo qual um desenvolvedor deve ser responsável.

A postagem tutorial do Grand Central Dispatch apareceu primeiro em LogRocket Blog .