多线程基本使用方法

  关于多线程的使用属于重点掌握知识,今天总结一下自己已经学到的多线程使用方法。多线程使用方法现阶段主要使用了3种。1:GCD(个人觉得这个属于最常用方法,因为其贴近底层,执行效率更高) 2.

NSOperation(使用率较高,属于苹果封装好的GCD类,面向对象更好理解) 3.NSThread(个人使用较少,创建好对象后需要自己手动启动线程)

1.GCD

多条异步线程启用,此方法中首先创建一个异步队列,因为所有的线程都需要加入队列才能得到使用,然后创建4个子线程操作加入队列,这样异步线程开启,GCD会自动管理线程,我们只需要关心我们要做什么操作即可

 1 - (void)demo1{
 2    /**  优先级
 3    *  #define DISPATCH_QUEUE_PRIORITY_HIGH 2      优先
 4    *  #define DISPATCH_QUEUE_PRIORITY_DEFAULT 0   正常
 5    *  #define DISPATCH_QUEUE_PRIORITY_LOW (-2)    低
 6    *  #define DISPATCH_QUEUE_PRIORITY_BACKGROUND INT16_MIN 后台
 7    */
 8   //创建异步队列
 9    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
10    //往队列里添加线程操作
11    dispatch_async(queue, ^{
12        NSLog(@"---下载图片1--%@",[NSThread currentThread]);
13    });
14    dispatch_async(queue, ^{
15       NSLog(@"---下载图片2--%@",[NSThread currentThread]);
16    });
17    dispatch_async(queue, ^{
18       NSLog(@"---下载图片3--%@",[NSThread currentThread]);
19    });
20    dispatch_async(queue, ^{
21      NSLog(@"---下载图片4--%@",[NSThread currentThread]);
22    });
23 }

从结果分析我们达到了多条线程异步下载的效果

异步串行队列

 1 - (void)demo2{
 2     /**
 3      *  串行队列创建
 4      *  @param "Myqueue.test" 标识符
 5      *  @param NULL           一般为NULL
 6      */
 7     dispatch_queue_t queue = dispatch_queue_create("Myqueue.test", NULL);
 8     //开启异步线程
 9     dispatch_async(queue, ^{
10         NSLog(@"---下载图片1--%@",[NSThread currentThread]);
11     });
12     dispatch_async(queue, ^{
13         NSLog(@"---下载图片2--%@",[NSThread currentThread]);
14     });
15     dispatch_async(queue, ^{
16         NSLog(@"---下载图片3--%@",[NSThread currentThread]);
17     });
18     dispatch_async(queue, ^{
19         NSLog(@"---下载图片4--%@",[NSThread currentThread]);
20     });
21 }

从此结果分析,异步串行队列实质上只开辟一个子线程,并且按顺序执行之前自己添加的操作

异步组队列

 1 - (void)demo3{
 2     //设置异步队列
 3     dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
 4     //设置组队列
 5     dispatch_group_t group = dispatch_group_create();
 6     dispatch_group_async(group, queue, ^{
 7         NSLog(@"---下载图片1--%@",[NSThread currentThread]);
 8     });
 9     dispatch_group_async(group, queue, ^{
10         NSLog(@"---下载图片2--%@",[NSThread currentThread]);
11     });
12     dispatch_group_async(group, queue, ^{
13         NSLog(@"---下载图片3--%@",[NSThread currentThread]);
14     });
15     dispatch_group_async(group, queue, ^{
16         NSLog(@"---下载图片4--%@",[NSThread currentThread]);
17     });
18     //组队列操作执行完成后调用
19     dispatch_group_notify(group, queue, ^{
20         NSLog(@"下载完成");
21     });
22 }

组队列操作的好处是让我们先执行某些操作 在操作执行完成后再执行什么操作。

2.NSOperation

NSOperation的使用一般都是基于其子类NSBlockOperation,使用方法如下

NSBlockOperation 使用

 1 - (void)demo4{
 2     //NSBlockOperation start使用方法
 3     dispatch_async(dispatch_queue_create("123", NULL), ^{
 4         NSBlockOperation *operation1 = [NSBlockOperation blockOperationWithBlock:^{
 5             NSLog(@"---下载图片1--%@",[NSThread currentThread]);
 6         }];
 7         //增加额外线程 addExecutionBlock 额外线程是在operation1主线程执行后 再异步执行
 8         [operation1 addExecutionBlock:^{
 9             NSLog(@"---下载图片2--%@",[NSThread currentThread]);
10         }];
11         [operation1 addExecutionBlock:^{
12             NSLog(@"---下载图片3--%@",[NSThread currentThread]);
13         }];
14         [operation1 addExecutionBlock:^{
15             NSLog(@"---下载图片4--%@",[NSThread currentThread]);
16         }];
17         //用start 直接使用当前线程
18         [operation1 start];
19     });
20 }

增加的额外线程只会在其第一个操作执行完成后再异步执行。这样当多个操作都依赖于一个操作完成时执行,此方法比较适用

说完NSBlockOperation,必须提一下NSOperationQueue的使用,因为一般NSBlockOperation对象都是加入NSOperationQueue对象中使用,这样不用自己手动启动线程

 1 - (void)demo5{
 2     //创建异步队列
 3     NSOperationQueue *queue = [[NSOperationQueue alloc] init];
 4     //创建主线程队列
 5 //    NSOperationQueue *queue = [NSOperationQueue mainQueue];
 6     //若为主线程 则相当于串行队列
 7     [queue addOperationWithBlock:^{
 8         NSLog(@"---下载图片1--%@",[NSThread currentThread]);
 9     }];
10     [queue addOperationWithBlock:^{
11         NSLog(@"---下载图片2--%@",[NSThread currentThread]);
12     }];
13     //创建操作
14     NSBlockOperation *operation1 = [NSBlockOperation blockOperationWithBlock:^{
15         NSLog(@"---下载图片1--%@",[NSThread currentThread]);
16     }];
17     NSBlockOperation *operation2 = [NSBlockOperation blockOperationWithBlock:^{
18         NSLog(@"---下载图片2--%@",[NSThread currentThread]);
19     }];
20     NSBlockOperation *operation3 = [NSBlockOperation blockOperationWithBlock:^{
21         NSLog(@"---下载图片3--%@",[NSThread currentThread]);
22     }];
23     NSBlockOperation *operation4 = [NSBlockOperation blockOperationWithBlock:^{
24         NSLog(@"---下载图片4--%@",[NSThread currentThread]);
25     }];
26     //将操作添加进队列
27     [queue addOperation:operation1];
28     [queue addOperation:operation2];
29     [queue addOperation:operation3];
30     [queue addOperation:operation4];
31 }

队列中所有操作都异步执行,其中

[queue addOperationWithBlock:^{
        NSLog(@"---A--%@",[NSThread currentThread]);
    }];

相当于

NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"---A--%@",[NSThread currentThread]);
    }];
[queue addOperation:operation];

这种写法方便了程序员编写代码,达到代码简化的效果,此处主队列串行的结果图就不上传了

异步队列依赖关系设置(达到上述GCD中组队列效果)

 1 - (void)demo7{
 2     //创建异步队列
 3     NSOperationQueue *queue = [[NSOperationQueue alloc] init];
 4     //创建操作
 5     NSBlockOperation *operationA = [NSBlockOperation blockOperationWithBlock:^{
 6         NSLog(@"-----A------");
 7     }];
 8     NSBlockOperation *operationB = [NSBlockOperation blockOperationWithBlock:^{
 9         NSLog(@"-----B------");
10     }];
11     NSBlockOperation *operationC = [NSBlockOperation blockOperationWithBlock:^{
12         NSLog(@"-----C------");
13     }];
14     //设置依赖关系 不能相互依赖
15     [operationB addDependency:operationA];
16     [operationC addDependency:operationA];
17     //将操作写进队列
18     [queue addOperation:operationA];
19     [queue addOperation:operationB];
20     [queue addOperation:operationC];
21 }

此处运行了2次demo,可以发现 B、C都是在A完成后才进行的操作。达到了依赖效果。

关于NSThread此处就不提了,因为其使用率较低,掌握好上述2中就能做好多线程开发。

如文中有何错误,希望大家指出!

时间: 2024-11-29 08:38:35

多线程基本使用方法的相关文章

Win32 多线程的创建方法,区别和联系

Win32多线程的创建方法主要有: CreateThread() _beginthread()&&_beginthreadex() AfxBeginThread() CWinThread类 一.简介 CreateThread: Win32提供的创建线程的最基础的API,用于在主线程上创建一个线程.返回一个HANDLE句柄(内核对象).在内核对象使用完毕后,一般需要关闭,使用CloseHandle()函数. _beginthread()&&_beginthreadex():_

一种非常简便的实现Android多线程池的方法

开发Android过程中至少会遇到一个主线程,也称UI线程,这个线程是不允许阻塞的,否则会报错,比如最常见的获取网络资源.读写文件等操作,这些耗时操作都不能再主线程使用.这里介绍一个非常高效又非常简单实用的方法ExecutorService类. ExecutorService类可以理解为线程池,开发者可以实例化一个该对象,在其中使用多个异步进行的操作. ExecutorService接口继承了Executor接口,定义了一些生命周期的方法,如下定义. public interface Execu

多线程的创建方法

- (void)viewDidLoad {    [super viewDidLoad]; //第一种开启新的线程调用 mutableTheard    NSThread * t = [[NSThread alloc]initWithTarget:self selector:@selector(mutableTheard) object:nil];    [t start];            //第二种开启新的线程调用 mutableTheard    [NSThread detachNe

Java多线程死锁避免方法

一.什么是死锁当两个或两个以上的线程在执行过程中,因为争夺资源而造成的一种相互等待的状态,由于存在一种环路的锁依赖关系而永远地等待下去,如果没有外部干涉,他们将永远等待下去,此时的这个状态称之为死锁.经典的 "哲学家进餐" 问题很好地描述了死锁状况:5个哲学家去吃中餐,坐在一张圆桌旁,他们有5根筷子(而不是5双),并且每两个人中间放一根筷子,哲学家们要么在思考,要么在进餐,每个人都需要一双筷子才能吃到东西,并在吃完后将筷子放回原处继续思考,有些筷子管理算法 (1) 能够使每个人都能相对

多线程的通信方法

转自 http://www.cnblogs.com/mengyan/archive/2012/08/30/2664607.html 一.进程通信方法 在说明线程通信前,有必要对进程通信进行说明: 进程间通信的方法主要有以下几种:  (1)管道(Pipe):管道可用于具有亲缘关系进程间的通信,允许一个进程和另一个与它有共同祖先的进程之间进行通信.  (2)命名管道(named pipe):命名管道克服了管道没有名字的限制,因此,除具有管道所具有的功能外,它还允许无亲缘关 系 进程间的通信.命名管道

多线程操作的方法(sleep,)setPriority(Thread.MIN_PRIORITY);yield();

在多线程中所有的操作方法都是从Thread类开始的,所有的操作基本都在Thread类中. 第一取得线程名字 a,在Thread类中,可以通过getName()方法,获得线程的名字,可以通过setName()方法设置线程的名字 b,线程名字一般在线程启动前设置,但是也允许为已经运行的线程设置名称,允许2个Thread对象有相 同的名字,但是不推荐,你懂的!!! c,如果程序没有为线程指定名字,则系统自动为线程分配一个名称. package xianchengcaozuo; public class

多线程NSOperation使用方法

/*------------------------------  NSOperation使用   -----------------------------------*/ 重点:操作 NSOperation 和操作队列 NSOperationQueue! { 1.NSOperation(操作)简介: NSOperation: // 本质是对 GCD 的封装, OC 语言. NSOperation 和 GCD 的比较: GCD使用场合: 一些简单的需求,简单的多线程操作. //简单高效 NSO

Java多线程同步的方法

一 synchronized关键字 1.synchronized实现原理: ---基于对象监视器(锁) java中所有对象都自动含有单一的锁,JVM负责跟踪对象被加锁的次数.如果一个对象被解锁,其计数变为0.在任务(线程)第一次给对象加锁的时候, 计数变为1.每当这个相同的任务(线程)在此对象上获得锁时,计数会递增.只有首先获得锁的任务(线程)才能继续获取该对象上的多个锁.每当任务离开时,计数递减,当计数为0的时候,锁被完全释放. Java中每个对象或者类都有一把锁与之相关联,对于对象来说,监视

Java 多线程的实现方法

package com.jckb; /**多线程实现的两种方法 * * @author gx * */ public class Test2 { public static void main(String[] args) { Mythread m = new Mythread(); m.start();// 不能直接调用run方法 // m.run();//是方法调用,不是线程的启动 Thread t = new Thread(new Mythread2()); t.start(); } }

Java多线程之~~~~synchronized 方法

在多线程开发中,总会遇到多个在不同线程中的方法操作同一个数据,这样在不同线程中操作这个数据不同的顺序 或者时机会导致各种不同的现象发生,以至于不能实现你预期的效果,不能实现一致性,这时候就可以使用 synchronized关键字对一个方法来说,这个synchronized能保证所有调用这个方法的线程只有一个正在操作这个方法, 不会出现同时多个线程进入这个方法的情况,下面我们来一个例子说明这个情况. 首先是一个Account类,这个类模拟账户,提供增加工资和减少工资的方法,当然,这个方法是被syn