1. 程式人生 > >多執行緒中佇列和同/非同步執行問題

多執行緒中佇列和同/非同步執行問題

佇列分為並行佇列和序列佇列,執行方式分為同步執行和非同步執行,那麼組合一下就有四種方式,下面我會用GCD來驗證和總結一下各個組合的特性。

併發佇列,同步執行

//併發佇列+同步執行
//不會開啟新執行緒,任務順序執行
-(void)test1{
    NSLog(@"併發佇列+同步執行");
    //DISPATCH_QUEUE_CONCURRENT  併發佇列
    dispatch_queue_t queue = dispatch_queue_create("test", DISPATCH_QUEUE_CONCURRENT);
    //dispatch_sync 同步執行
    dispatch_sync
(queue, ^{ for (int i = 0; i < 5; i ++) { NSLog(@"1------%@",[NSThread currentThread]); } }); dispatch_sync(queue, ^{ for (int i = 0; i < 5; i ++) { NSLog(@"2------%@",[NSThread currentThread]); } }); dispatch_sync(queue, ^{ for
(int i = 0; i < 5; i ++) { NSLog(@"3------%@",[NSThread currentThread]); } }); NSLog(@"end"); }

列印結果:

2018-08-30 11:30:39.604191+0800 GCD_demo[1890:93476] 併發佇列+同步執行
2018-08-30 11:30:39.604342+0800 GCD_demo[1890:93476] 1------<NSThread: 0x60c00007e740>{number = 1, name = main}
2018-08-30
11:30:39.604441+0800 GCD_demo[1890:93476] 1------<NSThread: 0x60c00007e740>{number = 1, name = main} 2018-08-30 11:30:39.604538+0800 GCD_demo[1890:93476] 1------<NSThread: 0x60c00007e740>{number = 1, name = main} 2018-08-30 11:30:39.604705+0800 GCD_demo[1890:93476] 1------<NSThread: 0x60c00007e740>{number = 1, name = main} 2018-08-30 11:30:39.604818+0800 GCD_demo[1890:93476] 1------<NSThread: 0x60c00007e740>{number = 1, name = main} 2018-08-30 11:30:39.604929+0800 GCD_demo[1890:93476] 2------<NSThread: 0x60c00007e740>{number = 1, name = main} 2018-08-30 11:30:39.604993+0800 GCD_demo[1890:93476] 2------<NSThread: 0x60c00007e740>{number = 1, name = main} 2018-08-30 11:30:39.605059+0800 GCD_demo[1890:93476] 2------<NSThread: 0x60c00007e740>{number = 1, name = main} 2018-08-30 11:30:39.605132+0800 GCD_demo[1890:93476] 2------<NSThread: 0x60c00007e740>{number = 1, name = main} 2018-08-30 11:30:39.605226+0800 GCD_demo[1890:93476] 2------<NSThread: 0x60c00007e740>{number = 1, name = main} 2018-08-30 11:30:39.605344+0800 GCD_demo[1890:93476] 3------<NSThread: 0x60c00007e740>{number = 1, name = main} 2018-08-30 11:30:39.605472+0800 GCD_demo[1890:93476] 3------<NSThread: 0x60c00007e740>{number = 1, name = main} 2018-08-30 11:30:39.605610+0800 GCD_demo[1890:93476] 3------<NSThread: 0x60c00007e740>{number = 1, name = main} 2018-08-30 11:30:39.605752+0800 GCD_demo[1890:93476] 3------<NSThread: 0x60c00007e740>{number = 1, name = main} 2018-08-30 11:30:39.605817+0800 GCD_demo[1890:93476] 3------<NSThread: 0x60c00007e740>{number = 1, name = main} 2018-08-30 11:30:39.605943+0800 GCD_demo[1890:93476] end

併發佇列同步執行時,任務都是順序執行的,且沒有開啟新的執行緒。

併發佇列,非同步執行

//併發佇列+非同步執行
//會開啟新的執行緒,任務執行無序
-(void)test2{
    NSLog(@"併發佇列+非同步執行");
    //DISPATCH_QUEUE_CONCURRENT  併發佇列
    dispatch_queue_t queue = dispatch_queue_create("test", DISPATCH_QUEUE_CONCURRENT);
    //dispatch_async 非同步執行
    dispatch_async(queue, ^{
        for (int i = 0; i < 10; i ++) {
            NSLog(@"1------%@",[NSThread currentThread]);
        }
    });
    dispatch_async(queue, ^{
        for (int i = 0; i < 10; i ++) {
            NSLog(@"2------%@",[NSThread currentThread]);
        }
    });
    dispatch_async(queue, ^{
        for (int i = 0; i < 10; i ++) {
            NSLog(@"3------%@",[NSThread currentThread]);
        }
    });
    NSLog(@"end");
}

列印結果:

2018-08-30 11:36:05.283473+0800 GCD_demo[1976:100239] 併發佇列+非同步執行
2018-08-30 11:36:05.283615+0800 GCD_demo[1976:100239] end
2018-08-30 11:36:05.283726+0800 GCD_demo[1976:100298] 1------<NSThread: 0x608000265980>{number = 3, name = (null)}
2018-08-30 11:36:05.283732+0800 GCD_demo[1976:100297] 3------<NSThread: 0x60c00027b880>{number = 5, name = (null)}
2018-08-30 11:36:05.283751+0800 GCD_demo[1976:100292] 2------<NSThread: 0x604000262bc0>{number = 4, name = (null)}
2018-08-30 11:36:05.283854+0800 GCD_demo[1976:100298] 1------<NSThread: 0x608000265980>{number = 3, name = (null)}
2018-08-30 11:36:05.283973+0800 GCD_demo[1976:100297] 3------<NSThread: 0x60c00027b880>{number = 5, name = (null)}
2018-08-30 11:36:05.284024+0800 GCD_demo[1976:100292] 2------<NSThread: 0x604000262bc0>{number = 4, name = (null)}
2018-08-30 11:36:05.284093+0800 GCD_demo[1976:100298] 1------<NSThread: 0x608000265980>{number = 3, name = (null)}
2018-08-30 11:36:05.284196+0800 GCD_demo[1976:100297] 3------<NSThread: 0x60c00027b880>{number = 5, name = (null)}
2018-08-30 11:36:05.284838+0800 GCD_demo[1976:100292] 2------<NSThread: 0x604000262bc0>{number = 4, name = (null)}
2018-08-30 11:36:05.284846+0800 GCD_demo[1976:100298] 1------<NSThread: 0x608000265980>{number = 3, name = (null)}
2018-08-30 11:36:05.284933+0800 GCD_demo[1976:100297] 3------<NSThread: 0x60c00027b880>{number = 5, name = (null)}
2018-08-30 11:36:05.285001+0800 GCD_demo[1976:100292] 2------<NSThread: 0x604000262bc0>{number = 4, name = (null)}
2018-08-30 11:36:05.285234+0800 GCD_demo[1976:100298] 1------<NSThread: 0x608000265980>{number = 3, name = (null)}
2018-08-30 11:36:05.285543+0800 GCD_demo[1976:100297] 3------<NSThread: 0x60c00027b880>{number = 5, name = (null)}
2018-08-30 11:36:05.285707+0800 GCD_demo[1976:100292] 2------<NSThread: 0x604000262bc0>{number = 4, name = (null)}
2018-08-30 11:36:05.285836+0800 GCD_demo[1976:100298] 1------<NSThread: 0x608000265980>{number = 3, name = (null)}
2018-08-30 11:36:05.286403+0800 GCD_demo[1976:100297] 3------<NSThread: 0x60c00027b880>{number = 5, name = (null)}
2018-08-30 11:36:05.286535+0800 GCD_demo[1976:100292] 2------<NSThread: 0x604000262bc0>{number = 4, name = (null)}
2018-08-30 11:36:05.286657+0800 GCD_demo[1976:100298] 1------<NSThread: 0x608000265980>{number = 3, name = (null)}
2018-08-30 11:36:05.287023+0800 GCD_demo[1976:100297] 3------<NSThread: 0x60c00027b880>{number = 5, name = (null)}
2018-08-30 11:36:05.287205+0800 GCD_demo[1976:100292] 2------<NSThread: 0x604000262bc0>{number = 4, name = (null)}
2018-08-30 11:36:05.287325+0800 GCD_demo[1976:100298] 1------<NSThread: 0x608000265980>{number = 3, name = (null)}
2018-08-30 11:36:05.287674+0800 GCD_demo[1976:100297] 3------<NSThread: 0x60c00027b880>{number = 5, name = (null)}
2018-08-30 11:36:05.287775+0800 GCD_demo[1976:100292] 2------<NSThread: 0x604000262bc0>{number = 4, name = (null)}
2018-08-30 11:36:05.287914+0800 GCD_demo[1976:100298] 1------<NSThread: 0x608000265980>{number = 3, name = (null)}
2018-08-30 11:36:05.288021+0800 GCD_demo[1976:100297] 3------<NSThread: 0x60c00027b880>{number = 5, name = (null)}
2018-08-30 11:36:05.288105+0800 GCD_demo[1976:100292] 2------<NSThread: 0x604000262bc0>{number = 4, name = (null)}
2018-08-30 11:36:05.288205+0800 GCD_demo[1976:100298] 1------<NSThread: 0x608000265980>{number = 3, name = (null)}
2018-08-30 11:36:05.288296+0800 GCD_demo[1976:100297] 3------<NSThread: 0x60c00027b880>{number = 5, name = (null)}
2018-08-30 11:36:05.288512+0800 GCD_demo[1976:100292] 2------<NSThread: 0x604000262bc0>{number = 4, name = (null)}

併發佇列非同步執行時,先執行了主執行緒的程式碼,然後開啟了新的執行緒執行各自的任務,任務執行無固定順序,每次執行的列印結果也不一定相同。

序列佇列,同步執行

//序列佇列+同步執行
//不會開啟新執行緒,任務順序執行
-(void)test3{
    NSLog(@"序列佇列+同步執行");
    //DISPATCH_QUEUE_SERIAL  序列佇列
    dispatch_queue_t queue = dispatch_queue_create("test", DISPATCH_QUEUE_SERIAL);
    //dispatch_sync 同步執行
    dispatch_sync(queue, ^{
        for (int i = 0; i < 10; i ++) {
            NSLog(@"1------%@",[NSThread currentThread]);
        }
    });
    dispatch_sync(queue, ^{
        for (int i = 0; i < 10; i ++) {
            NSLog(@"2------%@",[NSThread currentThread]);
        }
    });
    dispatch_sync(queue, ^{
        for (int i = 0; i < 10; i ++) {
            NSLog(@"3------%@",[NSThread currentThread]);
        }
    });
    NSLog(@"end");
}

列印結果:

2018-08-30 11:39:52.645772+0800 GCD_demo[2026:103893] 序列佇列+同步執行
2018-08-30 11:39:52.645956+0800 GCD_demo[2026:103893] 1------<NSThread: 0x600000076500>{number = 1, name = main}
2018-08-30 11:39:52.646063+0800 GCD_demo[2026:103893] 1------<NSThread: 0x600000076500>{number = 1, name = main}
2018-08-30 11:39:52.646147+0800 GCD_demo[2026:103893] 1------<NSThread: 0x600000076500>{number = 1, name = main}
2018-08-30 11:39:52.646216+0800 GCD_demo[2026:103893] 1------<NSThread: 0x600000076500>{number = 1, name = main}
2018-08-30 11:39:52.646307+0800 GCD_demo[2026:103893] 1------<NSThread: 0x600000076500>{number = 1, name = main}
2018-08-30 11:39:52.646403+0800 GCD_demo[2026:103893] 1------<NSThread: 0x600000076500>{number = 1, name = main}
2018-08-30 11:39:52.646481+0800 GCD_demo[2026:103893] 1------<NSThread: 0x600000076500>{number = 1, name = main}
2018-08-30 11:39:52.646605+0800 GCD_demo[2026:103893] 1------<NSThread: 0x600000076500>{number = 1, name = main}
2018-08-30 11:39:52.646681+0800 GCD_demo[2026:103893] 1------<NSThread: 0x600000076500>{number = 1, name = main}
2018-08-30 11:39:52.646747+0800 GCD_demo[2026:103893] 1------<NSThread: 0x600000076500>{number = 1, name = main}
2018-08-30 11:39:52.646820+0800 GCD_demo[2026:103893] 2------<NSThread: 0x600000076500>{number = 1, name = main}
2018-08-30 11:39:52.646909+0800 GCD_demo[2026:103893] 2------<NSThread: 0x600000076500>{number = 1, name = main}
2018-08-30 11:39:52.646972+0800 GCD_demo[2026:103893] 2------<NSThread: 0x600000076500>{number = 1, name = main}
2018-08-30 11:39:52.647053+0800 GCD_demo[2026:103893] 2------<NSThread: 0x600000076500>{number = 1, name = main}
2018-08-30 11:39:52.647140+0800 GCD_demo[2026:103893] 2------<NSThread: 0x600000076500>{number = 1, name = main}
2018-08-30 11:39:52.647294+0800 GCD_demo[2026:103893] 2------<NSThread: 0x600000076500>{number = 1, name = main}
2018-08-30 11:39:52.647442+0800 GCD_demo[2026:103893] 2------<NSThread: 0x600000076500>{number = 1, name = main}
2018-08-30 11:39:52.647514+0800 GCD_demo[2026:103893] 2------<NSThread: 0x600000076500>{number = 1, name = main}
2018-08-30 11:39:52.647629+0800 GCD_demo[2026:103893] 2------<NSThread: 0x600000076500>{number = 1, name = main}
2018-08-30 11:39:52.647765+0800 GCD_demo[2026:103893] 2------<NSThread: 0x600000076500>{number = 1, name = main}
2018-08-30 11:39:52.647866+0800 GCD_demo[2026:103893] 3------<NSThread: 0x600000076500>{number = 1, name = main}
2018-08-30 11:39:52.648214+0800 GCD_demo[2026:103893] 3------<NSThread: 0x600000076500>{number = 1, name = main}
2018-08-30 11:39:52.648290+0800 GCD_demo[2026:103893] 3------<NSThread: 0x600000076500>{number = 1, name = main}
2018-08-30 11:39:52.648397+0800 GCD_demo[2026:103893] 3------<NSThread: 0x600000076500>{number = 1, name = main}
2018-08-30 11:39:52.648477+0800 GCD_demo[2026:103893] 3------<NSThread: 0x600000076500>{number = 1, name = main}
2018-08-30 11:39:52.648680+0800 GCD_demo[2026:103893] 3------<NSThread: 0x600000076500>{number = 1, name = main}
2018-08-30 11:39:52.648844+0800 GCD_demo[2026:103893] 3------<NSThread: 0x600000076500>{number = 1, name = main}
2018-08-30 11:39:52.648980+0800 GCD_demo[2026:103893] 3------<NSThread: 0x600000076500>{number = 1, name = main}
2018-08-30 11:39:52.649131+0800 GCD_demo[2026:103893] 3------<NSThread: 0x600000076500>{number = 1, name = main}
2018-08-30 11:39:52.649276+0800 GCD_demo[2026:103893] 3------<NSThread: 0x600000076500>{number = 1, name = main}
2018-08-30 11:39:52.649345+0800 GCD_demo[2026:103893] end

序列佇列同步執行時,不會開啟新執行緒,任務順序執行。

序列佇列,非同步執行

//序列佇列+非同步執行
//會開啟一條新執行緒,順序執行任務
-(void)test4{
    NSLog(@"序列佇列+非同步執行");
    //DISPATCH_QUEUE_SERIAL  序列佇列
    dispatch_queue_t queue = dispatch_queue_create("test", DISPATCH_QUEUE_SERIAL);
    //dispatch_async 非同步執行
    dispatch_async(queue, ^{
        for (int i = 0; i < 10; i ++) {
            NSLog(@"1------%@",[NSThread currentThread]);
        }
    });
    dispatch_async(queue, ^{
        for (int i = 0; i < 10; i ++) {
            NSLog(@"2------%@",[NSThread currentThread]);
        }
    });
    dispatch_async(queue, ^{
        for (int i = 0; i < 10; i ++) {
            NSLog(@"3------%@",[NSThread currentThread]);
        }
    });
    NSLog(@"end");
}

列印結果:

2018-08-30 11:42:34.493681+0800 GCD_demo[2093:106736] 序列佇列+非同步執行
2018-08-30 11:42:34.493803+0800 GCD_demo[2093:106736] end
2018-08-30 11:42:34.493861+0800 GCD_demo[2093:106849] 1------<NSThread: 0x604000073b00>{number = 3, name = (null)}
2018-08-30 11:42:34.494018+0800 GCD_demo[2093:106849] 1------<NSThread: 0x604000073b00>{number = 3, name = (null)}
2018-08-30 11:42:34.494559+0800 GCD_demo[2093:106849] 1------<NSThread: 0x604000073b00>{number = 3, name = (null)}
2018-08-30 11:42:34.494908+0800 GCD_demo[2093:106849] 1------<NSThread: 0x604000073b00>{number = 3, name = (null)}
2018-08-30 11:42:34.495473+0800 GCD_demo[2093:106849] 1------<NSThread: 0x604000073b00>{number = 3, name = (null)}
2018-08-30 11:42:34.495707+0800 GCD_demo[2093:106849] 1------<NSThread: 0x604000073b00>{number = 3, name = (null)}
2018-08-30 11:42:34.495842+0800 GCD_demo[2093:106849] 1------<NSThread: 0x604000073b00>{number = 3, name = (null)}
2018-08-30 11:42:34.496156+0800 GCD_demo[2093:106849] 1------<NSThread: 0x604000073b00>{number = 3, name = (null)}
2018-08-30 11:42:34.496285+0800 GCD_demo[2093:106849] 1------<NSThread: 0x604000073b00>{number = 3, name = (null)}
2018-08-30 11:42:34.496489+0800 GCD_demo[2093:106849] 1------<NSThread: 0x604000073b00>{number = 3, name = (null)}
2018-08-30 11:42:34.496680+0800 GCD_demo[2093:106849] 2------<NSThread: 0x604000073b00>{number = 3, name = (null)}
2018-08-30 11:42:34.497072+0800 GCD_demo[2093:106849] 2------<NSThread: 0x604000073b00>{number = 3, name = (null)}
2018-08-30 11:42:34.497162+0800 GCD_demo[2093:106849] 2------<NSThread: 0x604000073b00>{number = 3, name = (null)}
2018-08-30 11:42:34.497303+0800 GCD_demo[2093:106849] 2------<NSThread: 0x604000073b00>{number = 3, name = (null)}
2018-08-30 11:42:34.498035+0800 GCD_demo[2093:106849] 2------<NSThread: 0x604000073b00>{number = 3, name = (null)}
2018-08-30 11:42:34.498943+0800 GCD_demo[2093:106849] 2------<NSThread: 0x604000073b00>{number = 3, name = (null)}
2018-08-30 11:42:34.499458+0800 GCD_demo[2093:106849] 2------<NSThread: 0x604000073b00>{number = 3, name = (null)}
2018-08-30 11:42:34.499930+0800 GCD_demo[2093:106849] 2------<NSThread: 0x604000073b00>{number = 3, name = (null)}
2018-08-30 11:42:34.500762+0800 GCD_demo[2093:106849] 2------<NSThread: 0x604000073b00>{number = 3, name = (null)}
2018-08-30 11:42:34.501457+0800 GCD_demo[2093:106849] 2------<NSThread: 0x604000073b00>{number = 3, name = (null)}
2018-08-30 11:42:34.501728+0800 GCD_demo[2093:106849] 3------<NSThread: 0x604000073b00>{number = 3, name = (null)}
2018-08-30 11:42:34.502122+0800 GCD_demo[2093:106849] 3------<NSThread: 0x604000073b00>{number = 3, name = (null)}
2018-08-30 11:42:34.502631+0800 GCD_demo[2093:106849] 3------<NSThread: 0x604000073b00>{number = 3, name = (null)}
2018-08-30 11:42:34.502946+0800 GCD_demo[2093:106849] 3------<NSThread: 0x604000073b00>{number = 3, name = (null)}
2018-08-30 11:42:34.503777+0800 GCD_demo[2093:106849] 3------<NSThread: 0x604000073b00>{number = 3, name = (null)}
2018-08-30 11: