Sök…


Introduktion

Grand Central Dispatch (GCD) är Apples svar på multithreading. Det är ett lätt ramverk för att utföra uppgifter synkront eller asynkront i köer och hanterar CPU-trådar för dig bakom kulisserna.

Relaterat ämne: Samtidighet

Skapa en sändningskö

Du kan skapa din egen kö med dispatch_queue_create

Objective-C

dispatch_queue_t queue = dispatch_queue_create("com.example.myqueue",  DISPATCH_QUEUE_SERIAL);

Snabb

// Before Swift 3
let queue = dispatch_queue_create("com.example.myqueue", DISPATCH_QUEUE_SERIAL)
// Swift 3
let queue = DispatchQueue(label: "com.example.myqueue") //default is serial queue, unless .concurrent is specified as an attribute otherwise

Få huvudkön

Huvudkön är utsändningskön där alla UI-uppdateringar sker och koden för UI-ändringar placeras.

Du måste komma till huvudkön för att uppdatera användargränssnittet efter avslutad en asynkron process som NSURLSession

Det finns två typer av huvudkösamtal synchronous och asynchronous . När du åberopar något synchronously betyder det att tråden som initierade den operationen kommer att vänta på att uppgiften ska slutföras innan du fortsätter. Asynchronous innebär att den inte kommer att vänta.

Kodmål-C

Synchronous huvudkösamtal

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

Asynchronous huvudkösamtal

dispatch_async(dispatch_get_main_queue(), ^{
   // do work here to Usually to update the User Interface
});

SWIFT 3

Asynchronous huvudkösamtal

DispatchQueue.main.async {

}

Synchronous huvudkösamtal

DispatchQueue.main.sync {

}

Fraktgrupp

DispatchGroup möjliggör en samlad synkronisering av arbetet. Du kan använda dem för att skicka in flera olika arbetsobjekt och spåra när alla är klara, även om de kanske körs i olika köer. Detta beteende kan vara till hjälp när man inte kan göra framsteg förrän alla angivna uppgifter är slutförda.

Ett scenario när detta kan vara användbart är om du har flera webbtjänstsamtal som alla måste slutföras innan du fortsätter. Till exempel måste du ladda ner flera uppsättningar data som måste behandlas av någon funktion. Du måste vänta på att alla webbtjänster ska slutföras innan du ringer funktionen för att bearbeta alla mottagna data.

Snabb 3

func doLongTasksAndWait () {
    print("starting long running tasks")
    let group = DispatchGroup()          //create a group for a bunch of tasks we are about to do
    for i in 0...3 {                     //launch a bunch of tasks (eg a bunch of webservice calls that all need to be finished before proceeding to the next ViewController)
        group.enter()                    //let the group know that something is being added
        DispatchQueue.global().async {   //run tasks on a background thread
            sleep(arc4random() % 4)      //do some long task eg webservice or database lookup (here we are just sleeping for a random amount of time for demonstration purposes)
            print("long task \(i) done!")
            group.leave()                //let group know that the task is finished
        }
    }
    group.wait()                         //will block whatever thread we are on here until all the above tasks have finished (so maybe dont use this function on your main thread)
    print("all tasks done!")
}

Alternativt, om du inte vill vänta på att grupperna ska slutföras, men istället vill köra en funktion när alla uppgifter har slutförts, använd notify i stället för group.wait()

group.notify(queue: DispatchQueue.main) { //the queue: parameter is which queue this block will run on, if you need to do UI updates, use the main queue
    print("all tasks done!")              //this will execute when all tasks have left the group
}

Exempel på utgång:

starting long running tasks
long task 0 done!
long task 3 done!
long task 1 done!
long task 2 done!
all tasks done!

Mer information finns i Apple Docs eller det relaterade ämnet

Skicka Semaphore

DispatchSemaphore tillhandahåller en effektiv implementering av en traditionell räknesemafor, som kan användas för att kontrollera åtkomst till en resurs över flera exekveringssituationer.

Ett scenario för när du ska använda en semafor kan vara om du gör en filläsning / -skrivning, om flera uppgifter försöker läsa och skriva från fil på samma gång kan det öka din prestanda så att varje uppgift väntar sin tur så att för att inte överbelasta I / O-kontrollen.

Snabb 3

func do2TasksAtATime () {
    print("starting long running tasks (2 at a time)")
    let sem = DispatchSemaphore(value: 2)            //this semaphore only allows 2 tasks to run at the same time (the resource count)
    for i in 0...7 {                                 //launch a bunch of tasks
        DispatchQueue.global().async {               //run tasks on a background thread
            sem.wait()                               //wait here if no resources available
            sleep(2)                                 //do some long task eg file access (here we are just sleeping for a 2 seconds for demonstration purposes)
            print("long task \(i) done! \(Date())")
            sem.signal()                             //let the semaphore know this resource is now available
        }
    }
}

Exempel på utgång: (märk tidstämplarna)

starting long running tasks (2 at a time)
long task 0 done! 2017-02-16 07:11:53 +0000
long task 1 done! 2017-02-16 07:11:53 +0000
long task 2 done! 2017-02-16 07:11:55 +0000
long task 3 done! 2017-02-16 07:11:55 +0000
long task 5 done! 2017-02-16 07:11:57 +0000
long task 4 done! 2017-02-16 07:11:57 +0000
long task 6 done! 2017-02-16 07:11:59 +0000
long task 7 done! 2017-02-16 07:11:59 +0000

Mer information finns i Apple Docs

Seriella vs samtidiga köer

Snabb 3

Seriekö

func serialQueues () {
    let serialQueue = DispatchQueue(label: "com.example.serial") //default queue type is a serial queue
    let start = Date ()
    for i in 0...3 {                                             //launch a bunch of tasks
        serialQueue.async {                                      //run tasks on a background thread, using our serial queue
            sleep(2)                                             //do some long task eg webservice or database lookup
            let timeTaken = Date().timeIntervalSince(start)
            print("serial long task \(i) done! total time taken: \(timeTaken)")
        }
    }
}

Exempel på utgång:

serial long task 0 done! total time taken: 2.07241100072861
serial long task 1 done! total time taken: 4.16347700357437
serial long task 2 done! total time taken: 6.23209798336029
serial long task 3 done! total time taken: 8.30682599544525

Samtidig kö

func concurrentQueues () {
    let concurrentQueue = DispatchQueue(label: "com.example.concurrent", attributes: .concurrent) //explicitly specify the queue to be a concurrent queue
    let start = Date ()
    for i in 0...3 {            //launch a bunch of tasks
        concurrentQueue.async { //run tasks on a background thread, using our concurrent queue
            sleep(2)            //do some long task eg webservice or database lookup
            let timeTaken = Date().timeIntervalSince(start)
            print("concurrent long task \(i) done! total time taken: \(timeTaken)")
        }
    }
}

Exempel på utgång:

concurrent long task 3 done! total time taken: 2.07092100381851
concurrent long task 0 done! total time taken: 2.07087397575378
concurrent long task 2 done! total time taken: 2.07086700201035
concurrent long task 1 done! total time taken: 2.07089096307755

Diskussion

Som vi kan se av exemplen ovan kommer en seriekö att slutföra varje uppgift i den ordning de skickas till kön. Varje uppgift väntar på att den föregående uppgiften är klar innan den körs. När det gäller den samtidiga kön väntar inte varje uppgift på de andra i kön och körs så snart som möjligt; fördelen är att alla uppgifter i kön kommer att köras samtidigt på separata trådar, vilket gör att en samtidskön tar mindre tid än en seriekö.

Om ordning för utförande av uppgifter inte är viktigt, använd alltid en samtidig kö för bästa effektivitet.



Modified text is an extract of the original Stack Overflow Documentation
Licensierat under CC BY-SA 3.0
Inte anslutet till Stack Overflow